简体   繁体   English

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

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

I'm having problems sending a very small piece of data (a date) to another TcpClient running on the same computer. 我在将很小的数据(日期)发送到在同一台计算机上运行的另一个TcpClient时遇到问题。

In the code below you will see that it sleeps before closing the NetworkStream. 在下面的代码中,您将看到它在关闭NetworkStream之前就处于休眠状态。 If I remove the Sleep it causes an intermittent problem where the data doesn't turn up at the other end. 如果我删除了Sleep ,则会导致间歇性问题,即另一端的数据不会打开。

Am I doing something wrong here? 我在这里做错什么了吗?

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();
}

Some other information: 其他一些信息:

  • On some computers you can remove the Sleep without it causing a problem (slower computers perhaps?) 在某些计算机上,您可以删除Sleep而不会引起问题(可能是速度较慢的计算机?)
  • I've tried closing the NetworkStream with Close(int timeout) (instead of sleeping) but that didn't help. 我试图用Close(int timeout) (而不是睡眠) Close(int timeout) NetworkStream,但这没有帮助。
  • The 1000 millisecond value is arbitrary - I suspect that other values would work too. 1000毫秒的值是任意的-我怀疑其他值也可以使用。 The question is: why is it required in the first place? 问题是:为什么首先需要它?

Calling close with a timeout on a NetworkStream means that the network stream will stay open in the background for X time to allow remaining data to be sent. 在NetworkStream上以超时调用close表示网络流将在X后台在后台保持打开状态,以允许发送剩余数据。 In the background is important to note since your code is not blocked by this. 在后台需要特别注意,因为您的代码不会因此而受阻。 Because you encapsulate the tcpClient in a using statement, the client and internally the NetworkStream will be disposed directly after your call to close. 因为您将tcpClient封装在using语句中,所以在您关闭调用之后,将直接处理客户端以及内部的NetworkStream。 Sleep in this case works since it allows the data to be sent out and blocks your method in the meantime to prevent it from forcefully disposing of its resources. 在这种情况下,睡眠是可行的,因为它允许发送数据并同时阻塞您的方法,以防止其强制处置资源。

A cleaner solution would be to set an active LingerState on the TcpClient with a long enough timeout. 较干净的解决方案是在TcpClient上设置活动的LingerState并设置足够长的超时时间。 See: http://msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient.lingerstate.aspx 请参阅: http//msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient.lingerstate.aspx

If your receive queue is not empty (you got data in your receive buffer from the server that you haven't read, disposing the Socket (Client) sends a TCP RST (Resets the connection)) and the data in the send buffer is discarded ie if not already sent lost, otherwise it waits till the send buffer is empty and then terminates the tcp connection. 如果接收队列不为空(未读取的服务器中的接收缓冲区中有数据,则处置Socket(客户端)将发送TCP RST(重置连接)),并且发送缓冲区中的数据将被丢弃即,如果尚未发送丢失,则等待发送缓冲区为空,然后终止tcp连接。

One workaround is to close the send channel: 一种解决方法是关闭发送通道:

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

before closing the client (instead of thread.sleep), in this case the conneciton is not reset. 在关闭客户端之前(而不是thread.sleep),这种情况下不会重置连接。

Also .Flush() does nothing on a networkstream. 而且.Flush()在网络流上不执行任何操作。

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

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

相关问题 TcpClient的NetworkStream读取不完整的数据,除非调用Thread.Sleep(1) - TcpClient's NetworkStream reads incomplete data unless Thread.Sleep(1) is called NetworkStream不会刷新数据 - NetworkStream doesn't flush data 除非添加Thread.Sleep,否则无法使Task.Result返回字符串 - Can't get Task.Result to return string unless I add a Thread.Sleep 套接字的sendTo()不发送任何数据包,除非我明确地睡眠线程 - Socket's sendTo() doesn't send any packet unless I explicitly sleep the thread TcpListener和NetworkStream无法获取数据 - TcpListener and NetworkStream doesn't get data 我做错了什么,所以数据绑定目标不会受到数据绑定源的影响 - What am I doing wrong so the data binding target doesn't get affected by data binding source 如何确保NetworkStream在不关闭Stream或TcpClient的情况下立即发送数据? - How to ensure NetworkStream to send data immediately without closing the Stream or TcpClient? 我在用IQueryable做错什么 <T> ? - What am I Doing Wrong with IQueryable<T>? C#中的Thread.Sleep():它是否休眠了实例化对象的线程,或者我从中调用方法的线程? - Thread.Sleep() in C#: Does it sleep the thread the object was instantiated in, or the thread i am calling the method from? Thread.Sleep(0)不能像描述的那样工作? - Thread.Sleep(0) doesn't work as described?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM