确定 TCP 服务器中断开的连接
Determine broken connection in TCP server
我写了一个 tcp 服务器,每次接受客户端连接时,套接字实例 return 由 Accept
或 EndAccept
编辑,称为处理程序和对象中收集的许多其他信息称为 TcpClientConnection
,我需要在某些特定的时间间隔确定连接是否已连接,Socket.Connected
属性 不可靠,根据文档我应该使用 Poll
方法与 SelectRead
选项来做到这一点。
在测试场景中,我拔下客户端电缆,并等待建立在 handler.Poll(1, SelectMode.SelectRead)
上的警报中断,它应该 return 正确但从未发生过。
根据Socket.Poll的文档:
This method cannot detect certain kinds of connection problems, such as a broken network cable, or that the remote host was shut down ungracefully. You must attempt to send or receive data to detect these kinds of errors.
换句话说 - 轮询可用于检查某些数据是否已到达并且可用于您的本地 OS 网络堆栈。
如果您需要检测连接问题,您需要调用阻塞读取(例如 Socket.Receive
)
您还可以构建一个简单的初始化迷你协议来交换一些约定的 'hello' 来回消息。
这是一个简单的示例,您可以如何操作:
private bool VerifyConnection(Socket socket)
{
byte[] b = new byte[1];
try
{
if (socket.Receive(b, 0, 1, SocketFlags.None) == 0)
throw new SocketException(System.Convert.ToInt32(SocketError.ConnectionReset));
socket.NoDelay = true;
socket.Send(new byte[1] { SocketHelper.HelloByte });
socket.NoDelay = false;
}
catch (Exception e)
{
this._logger.LogException(LogLevel.Fatal, e, "Attempt to connect (from: [{0}]), but encountered error during reading initialization message", socket.RemoteEndPoint);
socket.TryCloseSocket(this._logger);
return false;
}
if (b[0] != SocketHelper.HelloByte)
{
this._logger.Log(LogLevel.Fatal,
"Attempt to connect (from: [{0}]), but incorrect initialization byte sent: [{1}], Ignoring the attempt",
socket.RemoteEndPoint, b[0]);
socket.TryCloseSocket(this._logger);
return false;
}
return true;
}
这从根本上是由 TCP 和 IP 协议的工作方式造成的。检测连接是否断开的唯一方法是通过连接发送一些数据。底层 TCP 协议将导致确认从接收方发送回发送方,从而允许检测到断开的连接。
这些文章提供了更多信息
Do I need to heartbeat to keep a TCP connection open?
我写了一个 tcp 服务器,每次接受客户端连接时,套接字实例 return 由 Accept
或 EndAccept
编辑,称为处理程序和对象中收集的许多其他信息称为 TcpClientConnection
,我需要在某些特定的时间间隔确定连接是否已连接,Socket.Connected
属性 不可靠,根据文档我应该使用 Poll
方法与 SelectRead
选项来做到这一点。
在测试场景中,我拔下客户端电缆,并等待建立在 handler.Poll(1, SelectMode.SelectRead)
上的警报中断,它应该 return 正确但从未发生过。
根据Socket.Poll的文档:
This method cannot detect certain kinds of connection problems, such as a broken network cable, or that the remote host was shut down ungracefully. You must attempt to send or receive data to detect these kinds of errors.
换句话说 - 轮询可用于检查某些数据是否已到达并且可用于您的本地 OS 网络堆栈。
如果您需要检测连接问题,您需要调用阻塞读取(例如 Socket.Receive
)
您还可以构建一个简单的初始化迷你协议来交换一些约定的 'hello' 来回消息。 这是一个简单的示例,您可以如何操作:
private bool VerifyConnection(Socket socket)
{
byte[] b = new byte[1];
try
{
if (socket.Receive(b, 0, 1, SocketFlags.None) == 0)
throw new SocketException(System.Convert.ToInt32(SocketError.ConnectionReset));
socket.NoDelay = true;
socket.Send(new byte[1] { SocketHelper.HelloByte });
socket.NoDelay = false;
}
catch (Exception e)
{
this._logger.LogException(LogLevel.Fatal, e, "Attempt to connect (from: [{0}]), but encountered error during reading initialization message", socket.RemoteEndPoint);
socket.TryCloseSocket(this._logger);
return false;
}
if (b[0] != SocketHelper.HelloByte)
{
this._logger.Log(LogLevel.Fatal,
"Attempt to connect (from: [{0}]), but incorrect initialization byte sent: [{1}], Ignoring the attempt",
socket.RemoteEndPoint, b[0]);
socket.TryCloseSocket(this._logger);
return false;
}
return true;
}
这从根本上是由 TCP 和 IP 协议的工作方式造成的。检测连接是否断开的唯一方法是通过连接发送一些数据。底层 TCP 协议将导致确认从接收方发送回发送方,从而允许检测到断开的连接。
这些文章提供了更多信息
Do I need to heartbeat to keep a TCP connection open?