繁体   English   中英

除非我在关闭NetworkStream之前先执行Thread.Sleep(),否则NetworkStream并不总是发送数据。 我究竟做错了什么?

[英]NetworkStream doesn't always send data unless I Thread.Sleep() before closing the NetworkStream. What am I doing wrong?

我在将很小的数据(日期)发送到在同一台计算机上运行的另一个TcpClient时遇到问题。

在下面的代码中,您将看到它在关闭NetworkStream之前就处于休眠状态。 如果我删除了Sleep ,则会导致间歇性问题,即另一端的数据不会打开。

我在这里做错什么了吗?

using (TcpClient client = new TcpClient())
{
    client.Connect(new IPEndPoint(IPAddress.Loopback, _tcpServerPort));
    NetworkStream clientStream = client.GetStream();

    byte[] buffer = new ASCIIEncoding().GetBytes(theDateObject.ToString("yyyy-MM-dd HH:mm:ss"));                            
    clientStream.Write(buffer, 0, buffer.Length);
    clientStream.Flush();
    System.Threading.Thread.Sleep(1000); // Remove this line and the data may not arrive at the other end
    clientStream.Close();
}

其他一些信息:

  • 在某些计算机上,您可以删除Sleep而不会引起问题(可能是速度较慢的计算机?)
  • 我试图用Close(int timeout) (而不是睡眠) Close(int timeout) NetworkStream,但这没有帮助。
  • 1000毫秒的值是任意的-我怀疑其他值也可以使用。 问题是:为什么首先需要它?

在NetworkStream上以超时调用close表示网络流将在X后台在后台保持打开状态,以允许发送剩余数据。 在后台需要特别注意,因为您的代码不会因此而受阻。 因为您将tcpClient封装在using语句中,所以在您关闭调用之后,将直接处理客户端以及内部的NetworkStream。 在这种情况下,睡眠是可行的,因为它允许发送数据并同时阻塞您的方法,以防止其强制处置资源。

较干净的解决方案是在TcpClient上设置活动的LingerState并设置足够长的超时时间。 请参阅: http//msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient.lingerstate.aspx

如果接收队列不为空(未读取的服务器中的接收缓冲区中有数据,则处置Socket(客户端)将发送TCP RST(重置连接)),并且发送缓冲区中的数据将被丢弃即,如果尚未发送丢失,则等待发送缓冲区为空,然后终止tcp连接。

一种解决方法是关闭发送通道:

    client.Client.Shutdown(SocketShutdown.Send)
    clientStream.Close();
}

在关闭客户端之前(而不是thread.sleep),这种情况下不会重置连接。

而且.Flush()在网络流上不执行任何操作。

参见: http : //cs.baylor.edu/~donahoo/practical/JavaSockets/RecvQClose.pdf

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM