假设我们有一个带有.NET TcpListener
的基本TCP服务器,其基本TCP客户端使用.NET TcpClient
。
有哪些类型的连接终端,以及它们应该如何检查和处理?
客户端
一个。客户端正常终止连接。服务器会收到通知。
B中。客户端物理断开与网络的连接。服务器如何知道?
℃。客户端程序在没有正常断开连接的情况下关闭。服务器如何知道?
服务器
一个。服务器正常终止连接。客户端会收到通知。
B中。服务器物理断开与网络的连接。客户如何知道?
℃。服务器程序在没有正常断开连接的情况下关闭。客户如何知道?
答案 0 :(得分:3)
案例A和C由TCP数据包传送,标头中设置了FIN
标志。它由OS中的TCP / IP堆栈发送,因此如果应用程序异常退出并不重要。操作系统也失败的C的子例将代替B。
案例B,当您失去沟通能力时,会更复杂。如果故障是本地故障(例如,从WiFi接入点解除关联),则连接的本地端将立即发现网络状态的变化,并且可以推断连接已断开(但如果未清除,则连接可以在短期停电中存活下来。)
如果连接正在主动传输数据,则确认将超时并导致重新传输尝试。可能会对重新传输尝试施加限制,从而导致错误。
如果没有流量,则可能会在很长时间(多天)内未检测到连接丢失。因此,TCP连接通常配置为发送心跳包,必须进行确认,并以与普通数据相同的方式检测重传尝试失败。
答案 1 :(得分:1)
简短的回答是:当对方断开时,他们都不知道。当然,东西让你知道.TCP不是一个物理连接,因此它依赖于某种信号来确定状态。通常是通过检查连接或从另一侧接收正常的断开连接消息。有多种方法可以检查连接(轮询,超时,捕获套接字异常等)。这实际上取决于您使用的框架以及您的需求。
如果您有资源进行轮询,那么您可以轮询x秒并检查状态。等
Check this extension method found here
static class SocketExtensions
{
public static bool IsConnected(this Socket socket)
{
try
{
return !(socket.Poll(1, SelectMode.SelectRead) && socket.Available == 0);
}
catch (SocketException) { return false; }
}
}
基本上,如果连接打开并且有数据,则socket.Poll()返回true,否则如果没有连接则返回true。 socket.Available将返回发送的字节数。如果它是0,&& .Poll()是真的,然后连接被有效关闭。如果你试图遵循真/假的话会让人感到困惑,但这会很准确地回归。