背景/平台:
.NET 4 / C#
我有一个C#TcpClient
通过以太网连接到嵌入式设备。
我使用两个定时器 - 一个用于将接收的数据存储到本地Queue<MyMessage>
,另一个用于通过TCP将数据从另一个Queue<MyMessage>
发送到嵌入式设备。这两个都运行200 ms
并发送/读取他们必须发送/读取的任何内容。
还有另一个定时器发送保持活动数据包every second
(目前仅用于调试目的)。
情景/问题
建立连接后,嵌入式设备开始向我的TcpClient
发送一些数据。这可以按预期工作(请参阅下面的消息日志)。但是,我关闭设备(因此它根本不起作用)。这意味着它甚至无法正确关闭TCP。但那没关系。我想测试如果在真实情况下发生类似的事情会发生什么。
但是,即使服务器(设备)不再在线,TcpClient仍会继续发送数据。
以下是发送代码(使用NetworkStream.Write
):
while (messagesToSend.Count > 0)
{
MyMessage msg = messagesToSend.Dequeue();
clientStream.Write(msg.Data, 0, msg.Data.Length);
Debug.WriteLine(DateTime.Now.ToString() + " Sent: " + msg.MessageID);
}
发送继续持续45-50秒,然后最终中断。 这些是为TcpClient和NetworkStream
设置的选项client.LingerState = new LingerOption(true, 0);
client.NoDelay = true;
client.SendTimeout = 3000;
clientStream.WriteTimeout = 3000;
这是调试输出:
16:32:02 Connecting
16:32:02 Authorizing
16:32:02 Sent: 255
16:32:02 Sent: 0
16:32:02 Authorized
16:32:02 Connected
16:32:02 Received: 255
16:32:02 Received: 226
...
... some regular communication here
...
16:32:06 Received: 251
16:32:06 Sent: 0
16:32:07 Received: 251
16:32:07 Sent: 0 // At this point I have turned off the device
16:32:08 Sent: 0
16:32:09 Sent: 0
...
... every second the same message
...
16:32:54 Sent: 0
16:32:55 Sent: 0
16:32:56 Sent: 0
16:32:57 Unable to write data to the transport connection: An established connection was aborted by the software in your host machine.
16:32:57 CommunicationError
为什么连接需要这么长时间才能意识到它已关闭?如果主机没有响应,NetworkStream.Write
不应该立即失败吗?
如何检测设备电源被切断,连接不再有效?
答案 0 :(得分:1)
你做不到。如果您之间有交换机/路由器,您会如何检测到这一点?您的计算机仍然完全连接。
TCP / IP以这种方式工作。没有收件人确认的任何数据包的重新发送(通常会增加超时)。超时值和重新发送的数量是特定于tcp堆栈/操作系统的实现。
TcpClient.SendTimeout属性仅控制在流中向下发送数据所需的时间。
在调用Write方法之后,底层Socket返回实际发送到主机的字节数。 SendTimeout属性确定TcpClient在接收返回的字节数之前将等待的时间。如果超时在Send方法成功完成之前到期,则TcpClient将抛出SocketException。默认情况下没有超时。