我正在寻找如何在使用 TcpListener 时检测“客户端断开连接”。
所有的答案似乎都与这个类似: TcpListener:如何检测客户端断开连接?
基本上,从流中读取,如果 Read() 返回 0,则客户端已断开连接。
但这是假设客户端在它发送的每个数据流之后断开连接。我们在 TCP 连接/断开开销既缓慢又昂贵的环境中运行。
我们建立一个连接,然后我们发送一些请求。
伪代码:
client.Connect();
client.GetStatus();
client.DoSomething();
client.DoSomethingElse();
client.AndSoOn();
client.Disconnect();
Run Code Online (Sandbox Code Playgroud)
Connect 和 Disconnect() 之间的每次调用都会向服务器发送一个数据流。服务器知道如何分析和处理流。
如果让 TcpListener 在不断开连接的情况下循环读取,它会读取并处理所有消息,但是在客户端断开连接后,服务器无法知道这一点,并且永远不会释放客户端并接受新消息。
var read = client.GetStream().Read(buffer, 0, buffer.Length);
if (read > 0)
{
//Process
}
Run Code Online (Sandbox Code Playgroud)
如果我让 TcpListener 在 read == 0 时删除客户端,它只接受第一个数据流,然后立即删除客户端。
当然,这意味着新客户端可以连接。
调用之间没有人为延迟,但就计算机时间而言,两次调用之间的时间当然是“巨大的”,因此总会有 read == 0 的时间,即使这并不意味着客户端已经或应该断开连接。
var read = client.GetStream().Read(buffer, 0, buffer.Length);
if (read > 0)
{
//Process
}
else
{
break; //Always executed as soon as the first stream of data has been received
}
Run Code Online (Sandbox Code Playgroud)
所以我想知道......有没有更好的方法来检测客户端是否已断开连接?
您可以使用该NetworkStream.Socket属性获取底层套接字并使用它的Receive方法进行读取。
与 不同的是NetworkStream.Read, 的链接重载Socket.Receive将阻塞,直到读取指定数量的字节为止,并且只有在远程主机关闭 TCP 连接时才会返回零。
更新: @jrh 的评论是正确的,它NetworkStream.Socket是受保护的属性,无法在此上下文中访问。为了获取 client Socket,您可以使用TcpListener.AcceptSocket方法,该方法返回Socket与新建立的连接相对应的对象。
| 归档时间: |
|
| 查看次数: |
14819 次 |
| 最近记录: |