我应该怎么做才能完全关闭与mcu的tcpClient连接?

What should I do to completely close the tcpClient connection with mcu?

我现在正在处理与 ESP32 中的 tcp 服务器 运行 的 tcp 套接字连接。 它可以很好地进行通信,但我未能关闭连接。 在close/reset tcpClient上搜索解决方案后,似乎关闭tcpClient的正确方法应该是:

tcpClient.GetStream().Close();
tcpCLient.Close();

example in msdn也用这个方法

但很遗憾,它无法真正关闭连接。正如在 mcu 中检查的那样,连接尚未关闭。即使我稍后关闭应用程序,它也不会关闭。这种情况下,mcu的tcp连接无法释放,无法接收其他连接。所以,我认为这不应该是关闭 tcpClient 的正确解决方案。

如果我不执行上面的语句,直接关闭应用程序,是可以成功关闭连接的。并且释放了mcu的tcp连接。 application close 好像做了什么,可以真正关闭连接。

在某些情况下,我需要在一些操作后关闭连接,然后重新连接。所以,我不能依赖应用程序关闭。

我已经尝试了以下所有方法的不同组合,但其中 none 可以成功释放 tcpClient 连接:

 tcpClient.Close(); 
 tcpClient.Client.Close();
 tcpClient.GetStream().Close();
 tcpClient.Client.Disconnect(true);
 tcpClient.Client.Disconnect(false);
 tcpClient.Dispose();
 tcpClient.Client.Dispose();
 tcpCLient = null;

也许应该按正确的顺序使用上面的一些命令来完成。

有谁知道我怎么不能自己关闭连接

提前致谢。

如您所述,这是关闭 TcpClient 的正确方法:

tcpClient.GetStream().Close();
tcpCLient.Close();

Close() 最终会关闭连接。查看 TcpClient.Close()

的文档

The Close method marks the instance as disposed and requests that the associated Socket close the TCP connection. Based on the LingerState property, the TCP connection may stay open for some time after the Close method is called when data remains to be sent. There is no notification provided when the underlying connection has completed closing.

您可以通过更改 TcpClient 对象的 LingerState 属性 来获得您想要的行为。

tcpClient.LingerState = new LingerOptions(true, 0);

使用WireShark研究网络包后,发现问题是由于发送RST延迟造成的,MSDN中建议的代码:

tcpClient.GetStream().Close();
tcpCLient.Close();

连加都没有区别

tcpClient.LingerState = new LingerOptions(true, 0);

因为它会立即发送FIN,而不是Close方法后的RST,所以会在2分钟左右发送。不幸的是,即使您在发出 tcpClient close 后关闭应用程序,它也不会被发送。

如果您在关闭 tcpClient 之前关闭应用程序,它将立即发送 RST。

以便它可以立即关闭服务器中的连接。

经过测试不同的命令组合,发现下面的代码确实可以立即关闭连接,但是大约40秒后会有另一个RST。

tcpClient.Client.Close();
tcpClient.Close();

不要调用 tcpClient.GetStream().Close(); !!!会造成RST的延迟。

我不知道这样关闭连接有没有影响,但这是我真正可以立即关闭连接的唯一方法。