簡體   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