我在生产环境中经历了一些随机的TCP断开连接:Windows Embedded中的高负载服务器和Windows XP中的客户端位于LAN中,通过Switcher通过长期TCP连接,大多数数据流是从服务器到客户端
服务器端核心代码是直接的,我简化为:
try
{
TcpListener tcpListener = new TcpListener(System.Net.IPAddress.Any, 8190);
tcpListener.Start();
var tcpClient = tcpListener.AcceptTcpClient();
var ns = tcpClient.GetStream();
ns.Write(bytes);
}
catch (Exception ex)
{
}
catch
中的随机异常是:
System.IO.IOException:无法将数据写入传输连接:连接尝试失败,因为连接方在一段时间后没有正确响应,或者由于连接的主机无法响应而建立连接失败。
我理解这个异常,因为客户端没有响应来自服务器的某些TCP请求(某些底层TCP级别ACK或某些事件),但问题是在某些情况下,异常只是在4或5秒内从{{{ 1}}被叫。
所以问题1 ,因为我没有为ms.WriteTo(ns);
对象指定任何超时值,为什么写超时这么短?建立连接时TCP可能具有动态超时设置(基于往返时间或sth),但应该更长(我猜)。
==============================
然后我写了一个小程序来模拟情况,我定期从服务器发送数据到客户端,突然我拔掉客户端机器中的电缆,让我感到惊讶的是TcpClient
in服务器端仍然可以像ns.Write(bytes)
调用一样顺畅地调用,但是在我拔掉电缆后不会立即弹出预期的阻塞调用和异常。
问题2,如果async
的行为如此,那么我们永远不知道哪些数据已成功发送到另一方,这就是我们使用TCP的原因。
===============================
拔掉电缆,我仍然保留Write
数据,我注意到当我发送的数据达到一定数量(可能是100字节),然后离线时间达到30秒,异常提出并使我感到困惑:< / p>
System.IO.IOException: 无法将数据写入传输连接:现有的 连接被远程主机强行关闭。 ---&GT; System.Net.Sockets.SocketException:现有连接是 由远程主机强行关闭 System.Net.Sockets.Socket.Send(Byte []缓冲区,Int32偏移量,Int32 大小,所以cketFlags socketFlags)at System.Net.Sockets.NetworkStream.Write(Byte []缓冲区,Int32偏移量, Int32尺寸)
如果我只发送几个字节,那就永远不会有例外。 那么问题3,TCP数据未能到达另一方可能不会在发送方提出任何通知? 问题4是谁在描述的异常中关闭了连接?由于客户端完全消失,我预计会有一个超时例外。