Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 当TCP客户端被强制关闭时,服务器无法识别断开连接 介绍_C#_Sockets_Networking_Tcp - Fatal编程技术网

C# 当TCP客户端被强制关闭时,服务器无法识别断开连接 介绍

C# 当TCP客户端被强制关闭时,服务器无法识别断开连接 介绍,c#,sockets,networking,tcp,C#,Sockets,Networking,Tcp,我的客户端应用程序的一个实例将与远程服务器建立两个传出TCP连接—一个主连接和一个文件传输连接 当客户端应用程序被强制关闭时——有时服务器不确认两个套接字连接都已断开 服务器将检测到两个连接都已断开,或者只断开了主连接,这是不需要的 了解问题只发生在多台测试机器中的一台上,并且当客户端被强制关闭时,文件传输连接正在积极传输数据 在分析了网络流量之后,我了解到操作系统实际上正在确认两个RST标志!因此,我倾向于认为问题在于服务器代码 代码 使用Socket.BeginReceive方法,我的回调主

我的客户端应用程序的一个实例将与远程服务器建立两个传出TCP连接—一个主连接和一个文件传输连接

当客户端应用程序被强制关闭时——有时服务器不确认两个套接字连接都已断开

服务器将检测到两个连接都已断开,或者只断开了主连接,这是不需要的

了解问题只发生在多台测试机器中的一台上,并且当客户端被强制关闭时,文件传输连接正在积极传输数据

在分析了网络流量之后,我了解到操作系统实际上正在确认两个RST标志!因此,我倾向于认为问题在于服务器代码

代码 使用
Socket.BeginReceive
方法,我的回调主要负责检测断开连接,如下所示:

private void ReadCallback(IAsyncResult asyncResult) 
{
    try 
    {
        int bytesTransferred = _clientSocket.EndReceive(asyncResult);
        _logger.Debug(GetHashCode() + " Received " + bytesTransferred + " bytes from " + RemoteEndPoint);

        if (bytesTransferred > 0) 
        {
            _clientSocket.BeginReceive(_readMessageBuffer, ReadCallback);
            _logger.Debug(GetHashCode() + " Issued asynchronous read for " + RemoteEndPoint);
        } 
        else 
        {
            _logger.Debug(GetHashCode() + " Client disconnected. Received zero bytes. ");
        }
    } 
    catch (SocketException socketException) 
    {
        _logger.DebugException(GetHashCode() + " Client disconnected. SocketException thrown", socketException);
    }
    catch (ObjectDisposedException objectDisposedException)
    {
        _logger.DebugException(GetHashCode() + " Client disconnected. ObjectDisposedException thrown", objectDisposedException);
    }
    catch (Exception exception) 
    {
        _logger.DebugException(GetHashCode() + " Client disconnected. Exception thrown", exception);
    }
}
为了隔离问题,我将代码剥离回去,以便服务器仅在每次从网络读取部分数据时发出异步读取

有人可以分享一些见解或猜测,为什么在某些机器上,服务器应用程序不会总是检测到两个套接字断开



我看到的第一件事是Socket.EndReceive调用周围没有异常处理程序。这个调用确实会抛出异常

您使用的是应该返回SocketError的版本,但文档中没有说明它在所有情况下都会返回SocketError

因为ReadCallback是由系统调用的,所以在EndReceive引发异常时,您不会有任何异常处理程序在链的更上层甚至可能捕获并打印错误。因此,似乎没有什么真正出了问题,但插座是半开的

我建议在Socket.EndReceive周围添加异常处理程序,并在发生异常时打印消息或设置断点。我认为这将指出问题所在。当从EndReceive获得异常时,您可能只需要处理/关闭套接字


希望对您有所帮助-Harold

您的代码没有问题。这是一个很好的解释发生了什么:

简而言之,您必须使用某种保持活动状态的消息来测试您的连接。如果客户端进程只是死掉,服务器可能永远不会收到关于它的通知,也永远不会意识到它

更多阅读:

计算机联网的关键在于信息在网络上传播。他们之间没有心理联系。如果一个端点消失,如果网络中断或计算机断电,就不会有灵能信号发送到另一端说“我再也不能和你说话了”


因此,唯一可靠地确定你正在与之交谈的计算机是否还在那里的方法是尝试与它交谈。当网络无法向计算机发送数据包时,您就会发现。但是,当一台计算机从“因为它没有什么可说而什么也不说”变成“因为它不在那里而什么也不说”时,你最终看到的只是它什么也没说。你看不出有什么区别。

你的代码看起来不错,我唯一能指出的是
如果在接收到0字节时不需要(socketError==socketError.Success)
。你所说的
是指文件传输连接保持半开放状态
?如果您试图在第一个连接断开时关闭第二个连接,则可能必须同时链接这两个连接并手动关闭另一个连接。请发布更多代码,以及任何相关的内容。您是在服务器没有注意到断开连接时看到RST,还是只是大体上观察到RST。您是否愿意采取变通办法(考虑超时和保留数据包)?@usr我真的很难相信这一点,但为了隔离问题,服务器应用程序只需对每个子套接字发出异步读取,如上所述。从网络读取的实际数据实际上被忽略,并且没有其他操作正在进行。@usr RST始终由服务器确认。我不想用keep-alive来抽象或隐藏问题。是的,这是有道理的。如果无法访问客户端,则会发生这种情况(例如,如果拔下客户端计算机上的网络电缆)。当发生这种情况时,您需要为何时取消异步读取设置计时器。更新该问题是为了让问题更清楚,并提供了奖励。也许你还有更多的猜测。嗨,Caster,我唯一能想到的是,当你第一次调用BeginReceive(在你发布的代码之外)时,你也没有捕捉到异常。你检查过那个箱子了吗?哈罗德:不幸的是,问题依然存在。无论如何,谢谢你。