まず問題を明確にします。TcpClient は scoket のカプセル化であり、TcpClient.Client は元のソケット オブジェクトです。
次に、 client.Client.Connected または client.Connected を使用して、まだ接続されているかどうかを判断することはできません。これは、このプロパティは、接続、アクティブな切断、または情報の送受信後にのみ更新され、リアルタイム状態ではないためです。
Microsoft によれば、ノンブロッキング 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; //恢复状态
}
}