2009-09-07 35 views
26

私はTcpClientを使いこなしていますが、接続が切断されたときにConnectedプロパティをfalseにする方法を理解しようとしています。TcpClient Connectionが閉じられているかどうかを確認するには?

私は

NetworkStream ns = client.GetStream(); 
ns.Write(new byte[1], 0, 0); 

をやってみました。しかしれるtcpClientが切断されている場合、それはまだ私には表示されません。あなたはTcpClientを使ってこれについてどうやって行きますか?

答えて

7

私が知っている限り、ソケットが読み書き以外に接続されているかどうかをテストする方法はありません。

私はTcpClientをまったく使用しませんでしたが、リモートエンドが正常にシャットダウンされた場合、SocketクラスはRead呼び出しから0を返します。 リモートエンドが正常にシャットダウンしない場合は、タイムアウト例外が発生します。そのタイプを覚えていないのは残念です。

'if(socket.Connected) { socket.Write(...) }のようなコードを使用すると、競合状態が発生します。 socket.Writeを呼び出し、例外や切断を処理する方が良いでしょう。

+0

うん。ソケットレイヤーは例外を使用して管理されます。 IOExceptionがスローされるリモートタイムアウトまたは閉鎖ソケットを検出するのに必要なすべての情報が含まれているのSocketExceptionに設定内部例外を有しています。 – Luca

-1

それは私

private void timer1_Tick(object sender, EventArgs e) 
    { 
     if (client.Client.Poll(0, SelectMode.SelectRead)) 
      { 
       if (!client.Connected) sConnected = false; 
       else 
       { 
        byte[] b = new byte[1]; 
        try 
        { 
         if (client.Client.Receive(b, SocketFlags.Peek) == 0) 
         { 
          // Client disconnected 
          sConnected = false; 
         } 
        } 
        catch { sConnected = false; } 
       } 
      } 
     if (!sConnected) 
     { 
      //--Basically what you want to do afterwards 
      timer1.Stop(); 
      client.Close(); 
      ReConnect(); 
     } 

    } 

私は定期的な間隔 で接続状態をチェックしたいといないコードを聞くとLOOPの[私はそれがsending-を遅くして感じた、ので、私はタイマーを使用のために働く、これを試してみてください受信プロセス]

+0

がこの回答を見つけたのは、それがなぜ投票されたのか不思議です。 – nagates

+1

は私のために動作しません、どちらもdownvoterのために私は、これは素晴らしい答えです – sotn0r

33

ソケットのテストのためだけに書き込みを試みることはお勧めできません。また、.NETのConnectedプロパティでもリレーしないでください。

あなたは、リモートエンドポイントがまだアクティブである場合、あなたはTcpConnectionInformation使用できるかを知りたい場合は、次の

TcpClient client = new TcpClient(host, port); 

IPGlobalProperties ipProperties = IPGlobalProperties.GetIPGlobalProperties(); 
TcpConnectionInformation[] tcpConnections = ipProperties.GetActiveTcpConnections().Where(x => x.LocalEndPoint.Equals(client.Client.LocalEndPoint) && x.RemoteEndPoint.Equals(client.Client.RemoteEndPoint)).ToArray(); 

if (tcpConnections != null && tcpConnections.Length > 0) 
{ 
    TcpState stateOfConnection = tcpConnections.First().State; 
    if (stateOfConnection == TcpState.Established) 
    { 
     // Connection is OK 
    } 
    else 
    { 
     // No active tcp Connection to hostName:port 
    } 

} 
client.Close(); 

関連項目:TcpState状態のMSDN
説明にMSDN
IPGlobalProperties
TcpConnectionInformation
Netstat on


ここでは、TcpClientの拡張メソッドです。

public static TcpState GetState(this TcpClient tcpClient) 
{ 
    var foo = IPGlobalProperties.GetIPGlobalProperties() 
    .GetActiveTcpConnections() 
    .SingleOrDefault(x => x.LocalEndPoint.Equals(tcpClient.Client.LocalEndPoint)); 
    return foo != null ? foo.State : TcpState.Unknown; 
} 
+2

を推測しません。あなたが改善できる唯一の方法は、ソケット状態を返すSocketの拡張メソッドとしてテストを提示することです。 –

+0

いいです。 –

+0

はありがとうのにそれを行うための任意のより高速な方法があれば、私は本当に不思議!あなたの答えは私のために働いた最初のものです。私はclient.Client.Pollを使っていろいろな回答を試みましたが、彼らは働いていませんでした。 –

2

@ urielの答えは私にはうってつけですが、私はC++/CLIでコード化する必要がありましたが、これはまったく問題ではありませんでした。ここには(ほぼ同等の)C++/CLIコードがあり、いくつかのロバストネスチェックが追加されています。

using namespace System::Net::Sockets; 
using namespace System::Net::NetworkInformation; 

TcpState GetTcpConnectionState(TcpClient^tcpClient) 
{ 
    TcpState tcpState = TcpState::Unknown; 

    if (tcpClient != nullptr) 
    { 
     // Get all active TCP connections 
     IPGlobalProperties^ipProperties = IPGlobalProperties::GetIPGlobalProperties(); 
     array<TcpConnectionInformation^>^tcpConnections = ipProperties->GetActiveTcpConnections(); 

     if ((tcpConnections != nullptr) && (tcpConnections->Length > 0)) 
     { 
      // Get the end points of the TCP connection in question 
      EndPoint^localEndPoint = tcpClient->Client->LocalEndPoint; 
      EndPoint^remoteEndPoint = tcpClient->Client->RemoteEndPoint; 

      // Run through all active TCP connections to locate TCP connection in question 
      for (int i = 0; i < tcpConnections->Length; i++) 
      { 
       if ((tcpConnections[i]->LocalEndPoint->Equals(localEndPoint)) && (tcpConnections[i]->RemoteEndPoint->Equals(remoteEndPoint))) 
       { 
        // Found active TCP connection in question 
        tcpState = tcpConnections[i]->State; 
        break; 
       } 
      } 
     } 
    } 

    return tcpState; 
} 

bool TcpConnected(TcpClient^tcpClient) 
{ 
    bool bTcpConnected = false; 

    if (tcpClient != nullptr) 
    { 
     if (GetTcpConnectionState(tcpClient) == TcpState::Established) 
     { 
      bTcpConnected = true; 
     } 
    } 
    return bTcpConnected; 
} 

うまくいけば、これは誰かに役立ちます。

2

クライアントがまだサーバーに接続されているかどうかを確認するために、私はこの機能を作成してくれました。

/// <summary> 
/// THIS FUNCTION WILL CHECK IF CLIENT IS STILL CONNECTED WITH SERVER. 
/// </summary> 
/// <returns>FALSE IF NOT CONNECTED ELSE TRUE</returns> 
public bool isClientConnected() 
{ 
    IPGlobalProperties ipProperties = IPGlobalProperties.GetIPGlobalProperties(); 

    TcpConnectionInformation[] tcpConnections = ipProperties.GetActiveTcpConnections(); 

    foreach (TcpConnectionInformation c in tcpConnections) 
    { 
     TcpState stateOfConnection = c.State; 

     if (c.LocalEndPoint.Equals(ClientSocket.Client.LocalEndPoint) && c.RemoteEndPoint.Equals(ClientSocket.Client.RemoteEndPoint)) 
     { 
      if (stateOfConnection == TcpState.Established) 
      { 
       return true; 
      } 
      else 
      { 
       return false; 
      } 

     } 

    } 

    return false; 


} 
+0

ありがとう、それは私の問題を解決します。 – Pratikk

0

私の場合は、(同じコンピュータ上の仮想マシンで実行されている)サーバーにいくつかのコマンドを送信し、応答を待っていました。しかし、待機中にサーバーが予期せず停止した場合、通知はありませんでした。私は他のポスターで提案された可能性を試しましたが、どちらもうまくいきませんでした(常にサーバーはまだ接続されていると言いました)。私にとっては、ストリームに0バイトを書き込むことだけが動作しています:

var client = new TcpClient(); 
//... open the client 

var stream = client.GetStream(); 

//... send something to the client 

byte[] empty = { 0 }; 
//wait for response from server 
while (client.Available == 0) 
{ 
    //throws a SocketException if the connection is closed by the server 
    stream.Write(empty, 0, 0); 
    Thread.Sleep(10); 
} 
1

ピーター・ウォーンとウリエルの解答はとてもいいです。しかし、ローカルエンドポイントへの複数のオープンな接続を持つことができるので、リモートエンドポイントもチェックする必要があります。

public static TcpState GetState(this TcpClient tcpClient) 
    { 
     var foo = IPGlobalProperties.GetIPGlobalProperties() 
      .GetActiveTcpConnections() 
      .SingleOrDefault(x => x.LocalEndPoint.Equals(tcpClient.Client.LocalEndPoint) 
          && x.RemoteEndPoint.Equals(tcpClient.Client.RemoteEndPoint) 
     ); 

     return foo != null ? foo.State : TcpState.Unknown; 
    }