关闭套接字和关闭网络流之间的区别(System.Net.Sockets)

时间:2018-04-14 05:59:50

标签: sockets tcp network-programming client-server tcpclient

我有一个代理服务器实现,如果我直接关闭套接字(System.Net.Sockets TCPClient.Client.Close())后发送最终响应给客户端然后客户端收到连接中止错误但是如果我使用系统.Net.Sockets TCPClient.getStream()。关闭(),它运行成功。我想了解有什么区别以及为什么客户端在第一个场景中收到错误?

2 个答案:

答案 0 :(得分:1)

我想说,关闭套接字并不是一件容易的操作,因为大多数人都认为:) 首先,您应该了解应如何正确完成关闭。基本上,你必须考虑close是一种消息,就像你的套接字发送的任何其他消息一样。或者说close()是对方完成某种工作的通信另一方的信息。 现在重要的是要了解具有TCP套接字,您可以通知对方您已完成发送或已完成侦听。 在此页面上,您可以查看它在后台的工作原理(请注意,ACK和FIN是IP层消息,因此即使使用普通套接字实现,您也永远不会看到它们):http://www.tcpipguide.com/free/t_TCPConnectionTermination-2.htm

所以现在更实际的一步。请考虑您有客户端和服务器。服务器需要接收消息并关闭连接。请考虑客户端只是发送消息然后关闭连接。如果您还认为网络需要一些时间来处理您的通信,您将意识到如果您快速完成,客户端将在服务器收到您的消息之前关闭连接。如果可以,TCPClient.Client.Close()客户端将停止侦听任何内容(这也意味着有关服务器关闭连接的信息)。所以这里是要播放的TCP堆栈(Windows为你做了) - 万一你将以这种方式关闭套接字,TCP堆栈,需要通知服务器站点任何已发送的服务器转到转储。这就是你有例外的原因。

所以正确的方法是:

  1. 通知服务器客户端已完成发送任何数据(FIN)
  2. 等到服务器确认他知道客户端不会发送任何数据(ACK)
  3. 现在服务器应该通知客户端将停止发送数据(FIN)
  4. 现在客户可以说 - “好吧,我知道了,我不再听了”(确认)
  5. 无论如何,C#TCPClient似乎隐藏了后台套接字关闭例程的逻辑,但是如果你不能以正确的方式调用close序列,那么你最终会出错。

    我希望这个有点长的解释能帮助你理解它在后台如何运作,最后让你理解为什么。

    如果您想了解更多信息,这也是了解有关TCP协议详细信息的更多信息的好方法:http://www.tcpipguide.com/free/t_TCPIPTransmissionControlProtocolTCP.htm

答案 1 :(得分:0)

我想为了关闭连接,你需要发送一些特殊的字节序列。看起来它只由tcpclient库实现,而不是由socket库实现。可能应该发送像Eof这样的东西。 您可以通过某些网络流量实用程序(如tcpdump)进行检查。 祝你好运!