1

我在将一小段数据(日期)发送到同一台计算机上运行的另一个 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)(而不是睡觉)关闭 NetworkStream,但这没有帮助。
  • 1000 毫秒的值是任意的——我怀疑其他值也可以。问题是:为什么首先需要它?
4

2 回答 2

1

在 NetworkStream 上使用超时调用 close 意味着网络流将在后台保持打开 X 时间以允许发送剩余的数据。在后台需要注意,因为您的代码不会被此阻止。因为您将 tcpClient 封装在 using 语句中,所以客户端和内部的 NetworkStream 将在您调用关闭后直接释放。在这种情况下,睡眠是有效的,因为它允许发送数据并在此期间阻止您的方法,以防止它强制处理其资源。

更简洁的解决方案是在 TcpClient 上设置一个活动的 LingerState,并具有足够长的超时时间。请参阅:http: //msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient.lingerstate.aspx

于 2012-10-19T08:15:18.023 回答
0

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

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

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

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

.Flush() 也对网络流没有任何作用。

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

于 2012-11-05T15:11:39.110 回答