即使没有连接,TcpClient也会持续发送一段时间

本文关键字:一段时间 TcpClient 连接 | 更新日期: 2023-09-27 18:01:50

背景/平台:

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不应该立即失败吗?

如何检测设备电源已断开,并且连接不再有效?

即使没有连接,TcpClient也会持续发送一段时间

你不能。如果你们之间有交换机/路由器,你会如何检测到这一点?您的计算机仍然完全连接。

TCP/IP就是这样工作的。任何未经接收方确认的数据包都会有一些重新发送(通常超时时间会增加(。超时值和重新发送的次数是特定于tcp堆栈/操作系统的实现。

TcpClient。SendTimeout属性只控制将数据进一步发送到流下游所需的时间。

调用Write方法后,底层Socket将返回实际发送到主机的字节数。SendTimeout属性确定TcpClient在接收返回的字节数之前等待的时间。如果在Send方法成功完成之前超时,TcpClient将抛出SocketException。默认情况下没有超时。