C# 如何防止.NET库在关闭时发送RST数据包
我正在做一些测试,试图隔离库(.NET)中的一些奇怪行为。当我通过C++使用Winsock API并简单调用,<代码>关闭SeCKOK()/CUT>时,我看到Windows端发送FIN/ACK包,而远端发送回ACK包。这就是我所说的优雅的接近。然而,当用C#编程时,我并没有看到我所说的优雅的结束 在C#中,我打开套接字,然后在关闭它时,我看到windows在第一次调用C# 如何防止.NET库在关闭时发送RST数据包,c#,.net,sockets,C#,.net,Sockets,我正在做一些测试,试图隔离库(.NET)中的一些奇怪行为。当我通过C++使用Winsock API并简单调用,关闭SeCKOK()/CUT>时,我看到Windows端发送FIN/ACK包,而远端发送回ACK包。这就是我所说的优雅的接近。然而,当用C#编程时,我并没有看到我所说的优雅的结束 在C#中,我打开套接字,然后在关闭它时,我看到windows在第一次调用socket.Shutdown()时仅发送一个FIN数据包。但是,无论如何,当我在C#中调用Socket.Close()时,会发送一个RS
socket.Shutdown()
时仅发送一个FIN数据包。但是,无论如何,当我在C#中调用Socket.Close()
时,会发送一个RST数据包,并立即断开连接。这让我感到困惑,因为从我在网上看到的内容来看,TCP关闭过程应该是FIN/ACK->ACK(实际上是从双方开始的,但现在,我只关心“我的”一方);i、 e.混合物中不应有RST数据包。从我所读到的,很明显,RST数据包只在接收者不确定连接状态并且想要退出时才被发送
为什么此RST数据包是在.NET的计划关机时发送的,而不是在winsock API的计划关机时发送的?在从.NET正常关闭期间,是否有方法防止RST数据包的传输
如果这很重要,在两个代码路径中,我在调用相应的
close()
方法之前读取套接字上的所有可用数据。最近遇到了一个类似的问题,应用程序正在与Exchange服务器进行POP3对话。当.NET程序完成时,它意外地关闭了,Exchange将POP3对话视为“中止”,并将其回滚
原因是我认为TCP RST是一个“单向”消息——您不必等待回复。因此,这就是.NET发送的内容(或者可能是终止后的任何程序)。一种可能的解决方案是在关闭套接字之后,在退出程序之前等待一段时间:
Thread.Sleep(5000);
这对我前面提到的POP3问题有效;等待时间导致连接正常关闭,Exchange不再中止会话。阅读的.NET文档,我发现:
对于面向连接的协议,建议您调用
在调用Close方法之前关闭。这确保了所有数据
在关闭之前,在连接的插座上发送和接收。如果
您需要在不首先调用Shutdown的情况下调用Close,您可以确保
排队等待传出传输的数据将通过设置
DontLinger套接字选项设置为false并指定非零超时
间隔Close随后将阻塞,直到发送此数据或
指定的超时过期。如果将DontLinger设置为false并指定
如果超时间隔为零,关闭将释放连接并
自动丢弃传出的排队数据
这是有道理的。如果缓冲区(OS one)中仍有数据,并且您中断了连接或终止了进程,则连接将被重置(TCP规范中有更详细的信息)
关于何时发送RST,请检查
我的猜测是,仍然有一些未设置或传输中的数据或在发送/输入缓冲区中触发RST。以下代码可能会阻止RST数据包。这是因为发送FIN数据包后等待60秒
socket.Close(60);
Close方法的描述是。在类似的情况下,我调用了
socket.Disconnect(false)
而不是socket.Close()
然后检查Wireshark过滤器发现,如果是RST/ACK,它会发送FIN/ACK。这很有趣。我得看看实施睡眠时会发生什么。我想知道还有什么会出现,因为我不认为这是可行的(如果它工作的话)在整个上下文中,这是发生的。我制作了一些框架程序来隔离行为。不过还是要谢谢你,因为我没想过在这里打电话睡觉。
if (theSenderSocket != null){
theSenderSocket.Disconnect(false);
}