首先明确一个问题,TcpClient是对scoket的封装,TcpClient.Client才是原本的socket对象。
其次不能用client.Client.Connected或者client.Connected来判断是不是还在连接,因为这个属性只有在 连接 或 主动断开连接 或 发送接收过信息后 才会更新,它并非一个实时的状态。
微软说可以调用非阻塞的Send(),发送一个0字节的消息,如果发送成功说明还在连接,如果抛出异常就已经断开连接,但是实验中发现并不行,远端断开后发送0字节消息依然不会报错,怀疑和TcpClient的封装有关,可能空消息直接就没法。所以改成发送1个字节,发现断开连接后正常报错。
检测连接方法如下,如果还在连接返回true,断开连接返回false
public bool IsSocketConnect(TcpClient client) //判断一个socket是否处于连接状态
{
if (client == null||client.Client == null)
{
return false;
}
//先看看状态
if (client.Client.Connected == false || client.Client.RemoteEndPoint == null)
{
return false;
}
//尝试发送以非阻塞模式发送一个消息 注意这个非阻塞模式不会影响异步发送
bool blockingState = client.Client.Blocking;
try
{
byte[] tmp = new byte[1];
client.Client.Blocking = false;
client.Client.Send(tmp, 1, 0);
return true;
}
catch (SocketException e)
{
// 产生 10035 == WSAEWOULDBLOCK 错误,说明被阻止了,但是还是连接的 这个错误是说发送缓冲区已满或者客户端的接收缓冲区已满
if (e.NativeErrorCode.Equals(10035))
return true;
else
return false;
}
finally
{
client.Client.Blocking = blockingState; //恢复状态
}
}