如何检测一个断开的套接字c#
本文关键字:断开 套接字 一个 何检测 检测 | 更新日期: 2023-09-27 17:50:14
我一直在c#中工作套接字客户端程序,我想知道如何检测套接字的另一端何时"不优雅地"断开连接,如在网线拔出或硬复位中。
我有下面这些函数来访问套接字,根据这里的SO问题和这篇MSDN文章,检查套接字是否断开连接的最佳方法是发送长度为0的1字节消息。如果抛出异常且WSAEWOULDBLOCK不是错误码,则套接字断开连接。我已经尝试过了,但是在硬重置服务器连接后,客户端将调用Send(new byte[1], 0, 0, SocketFlags.None)
并成功返回,之后Receive()
命令返回WSAEWOULDBLOCK错误。
给了什么? ?
下面是我的代码。_socket
设置为非阻塞模式:
private int nonBlockRecv(byte[] recvBytes, int offset, int size, SocketFlags sf)
{
int bytesRecv = 0;
while (true)
{
try
{
nonBlockSend(new byte[1], 0, 0, sf);
bytesRecv = _socket.Receive(recvBytes, offset, size, sf);
break;
}
catch (SocketException excp)
{
if (excp.ErrorCode != 10035) // WSAEWOULDBLOCK
throw excp;
}
}
return bytesRecv;
}
private int nonBlockSend(byte[] sendBytes, int offset, int size, SocketFlags sf)
{
int bytesSent = 0;
while (true)
{
try
{
_socket.Send(sendBytes, offset, size, sf);
break;
}
catch (SocketException excp)
{
if (excp.ErrorCode != 10035) // WSAEWOULDBLOCK
throw excp;
}
}
return bytesSent;
}
编辑:这可能是有益的,但服务器是Windows Mobile设备。我在另一个线程读到,不同的操作系统可能能够发送套接字关闭信号,当他们死亡。也许Windows Mobile操作系统不这样做??
如果远程计算机优雅地断开会话,则Socket.Receive()
方法将返回0字节。你必须察觉到要知道远端已断开连接:
int recv = sock.Receive(data);
if (recv == 0)
{
// Remote client has disconnected.
}
else
{
// Remote client has sent data.
}
此外,即使出现SocketException
,您也可以识别套接字断开的异常。
我知道这有点晚了,但我想出了一个巧妙的解决方案。
我必须与第三方软件进行通信,该软件希望在发送的每个命令上返回一个回车,否则它会忽略它。
在主阶段,我的客户端套接字处于接收第三方软件响应的循环中。我的解决方案并不理想,但基本的前提是,我在套接字上设置了一个接收超时,以便循环将尝试读取5秒,然后陷入catch,然后再次循环。在每次接收之前,我调用我自己的isconnected方法,它执行一个小的写操作,没有回车,所以它被第三方软件忽略,但如果网络掉线,它会给我一个可靠的故障切换。如果写失败,我所做的就是抛出一个LostConnectionException并从外部处理。
如果你同时编写服务器端和客户端代码,你可以很容易地提出一些对方忽略的校验数字。
这可能不完美,但对我来说是可靠的。
while (numberOfBytesRead == 0)
{
try
{
IsConnected();
_socket.ReceiveTimeout = 5000;
numberOfBytesRead = _socket.Receive(myReadBuffer, 0, myReadBuffer.Length, SocketFlags.None);
}
catch (Exception e)
{
if (e.GetType() == typeof (LostConnection))
{
Status = SocketStatus.offline;
throw;
}
}
}
和isconnected方法看起来像这样
public bool IsConnected(Socket s)
{
try
{
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes("test");
s.Send(buffer, 0, buffer.Length, SocketFlags.None);
}
catch (Exception)
{
throw new LostConnection();
}
return s.Connected;
}