我写了一个tcp服务器,每次接受客户端连接时,由Accept
或EndAccept
返回的套接字实例称为处理程序,并在名为TcpClientConnection
的对象中收集许多其他信息,我需要在某个特定的间隔时间确定连接是否已连接,Socket.Connected
属性不可靠,根据文档,我应该使用带有Poll
选项的SelectRead
方法做到这一点。
在测试场景中,我拔掉了客户端电缆,并等待handler.Poll(1, SelectMode.SelectRead)
上建立的破坏警报,它应该返回true但从未发生过。
答案 0 :(得分:2)
这主要是由TCP和IP协议的工作方式引起的。检测连接是否断开的唯一方法是通过连接发送一些数据。底层TCP协议将导致确认从接收方发送回发送方,从而允许检测到断开的连接。
这些文章提供了更多信息
答案 1 :(得分:1)
根据Socket.Poll的文档:
此方法无法检测某些类型的连接问题,例如网络电缆损坏,或者远程主机无法正常关闭。您必须尝试发送或接收数据以检测这些类型的错误。
换句话说 - 轮询对于检查某些数据是否到达并且可用于本地OS网络堆栈非常有用。
如果您需要检测连接问题,则需要调用阻止读取(例如Socket.Receive
)
您还可以构建一个简单的初始化miniprotocol来交换一些商定的'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;
}