C# 即使没有连接,TcpClient仍会发送一段时间

C# 即使没有连接,TcpClient仍会发送一段时间,c#,connection,send,tcpclient,C#,Connection,Send,Tcpclient,背景/平台: .NET 4/C# 我有一个C#TcpClient,通过以太网连接到嵌入式设备。 我正在使用两个计时器-一个用于将接收到的数据存储到本地队列,另一个用于通过TCP将数据从另一个队列发送到嵌入式设备。它们每200毫秒运行一次,并发送/读取它们必须发送/读取的任何内容 另一个计时器每秒发送一个保持活动的数据包(当前仅用于调试目的) 场景/问题 建立连接后,嵌入式设备开始向我的TcpClient发送一些数据。这可以按预期工作(请参阅下面的消息日志)。但是,我关闭设备(因此它根本不工作)。

背景/平台:

.NET 4/C#

我有一个C#
TcpClient
,通过以太网连接到嵌入式设备。 我正在使用两个计时器-一个用于将接收到的数据存储到本地
队列
,另一个用于通过TCP将数据从另一个
队列
发送到嵌入式设备。它们每200毫秒运行一次,并发送/读取它们必须发送/读取的任何内容

另一个计时器每秒发送一个保持活动的数据包
(当前仅用于调试目的)

场景/问题

建立连接后,嵌入式设备开始向我的
TcpClient
发送一些数据。这可以按预期工作(请参阅下面的消息日志)。但是,我关闭设备(因此它根本不工作)。这意味着它甚至无法正确关闭TCP。不过没关系。我想测试一下,如果在真实情况下发生这样的事情,会发生什么

但是,即使服务器(设备)不再联机,TcpClient仍会继续发送数据

以下是发送代码(使用
NetworkStream.Write
):

发送继续进行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
不应该立即失败吗


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

您不能。如果您之间有交换机/路由器,您将如何检测到这一点?您的计算机仍处于完全连接状态

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

该属性仅控制在流的下游发送数据所需的时间

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


因此,基本上,知道连接是否仍然有效的唯一方法是服务器(在我的情况下是设备)每XY秒向我发送一些自定义协议消息,然后如果我在XY秒(或稍多)内没有收到它,我就知道出了问题?我知道当连接失败时,读操作将返回0(因为已经接收到0个字节),但它似乎只在读操作时有效,而不是在写操作时有效。不是真的。数据包仍然可以在那里和这里之间的某个地方进行缓冲。唯一可以测量的是rtt(往返时间)。如果您确实想要构建您正在描述的内容,请切换到udp,它不实现重新发送(以及其他功能)。
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