【问题标题】:Tcpclient stream.ReadAsync does not return 0 when socket/stream closes?当套接字/流关闭时,Tcpclient stream.ReadAsync 不返回 0?
【发布时间】:2015-11-12 01:25:04
【问题描述】:

我正在使用 TcpClient.Stream.ReadAsync 循环接收数据。传统上,当套接字正常关闭时,Windows 套接字返回 0。使用以下代码,ReadAsync 返回的唯一时间是有实际数据时。如果我关闭远程应用程序(优雅或强制),或者即使我在 TcpClient 上调用 Stream.Close(),ReadAsync 仍然没有完成或抛出异常。如何让 ReadAsync 完成?

var amountRead = await stream.ReadAsync(conn.buffer, 0, Connection.BufferSize, ct);

if (amountRead == 0)
    break; //end of stream.
else
{
    //Process Received Data here
}

【问题讨论】:

  • 参见以下网页上的示例。这些示例适用于套接字,但可以将套接字替换为继承套接字的类,例如 TcpClient 或 TCPListener。 msdn.microsoft.com/en-us/library/w89fhyex(v=vs.110).aspx
  • 这实际上是不同的 Socket API,即 BeginSend 和 BeginReceive。我的问题是关于较新的 await/async api:ReadAsync。
  • 返回什么?
  • 顺便说一下,Stream.ReadAsync 只是 Stream.BeginReadStream.EndRead 的包装。
  • 根本不返回,没有错误码,没有异常。它返回的唯一时间是它实际接收到数据的时候。

标签: c# .net sockets async-await


【解决方案1】:

不,ReadAsync 的读取语义与BeginReadRead 完全相同。读取在流的末尾返回一个 0 字节的结果。

远程服务器可能没有正常关闭套接字。面向公众的服务器通常这样做是为了避免 4 次关闭握手。不幸的是,这意味着您作为客户端需要检测套接字何时关闭。传统上,这是通过使用保活消息或数据包来完成的。我有一个blog post with more details;但关键是它必须是 active 检测 - 即,客户端必须发送一些东西来检测连接不再存在。

顺便说一句,我不确定关闭 stream 会做什么。但我相当确定关闭 socket (TcpClient) 会导致流读取完成并出现错误。

【讨论】:

  • 我可以确认,如果发送数据的服务器没有优雅地关闭套接字(例如使用 StreamSocket.Dispose()),则 await stream.ReadAsync() 将永远不会返回。
猜你喜欢
  • 2014-01-23
  • 1970-01-01
  • 2023-02-24
  • 2011-01-15
  • 1970-01-01
  • 1970-01-01
  • 2011-06-11
  • 1970-01-01
  • 2011-07-25
相关资源
最近更新 更多