C# 如何防止.NET库在关闭时发送RST数据包

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

我正在做一些测试,试图隔离库(.NET)中的一些奇怪行为。当我通过C++使用Winsock API并简单调用,<代码>关闭SeCKOK()/CUT>时,我看到Windows端发送FIN/ACK包,而远端发送回ACK包。这就是我所说的优雅的接近。然而,当用C#编程时,我并没有看到我所说的优雅的结束

在C#中,我打开套接字,然后在关闭它时,我看到windows在第一次调用
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);
   }