87

クライアントがサーバーから切断されたことを検出するにはどうすればよいですか?

AcceptCallBackメソッドに次のコードがあります

static Socket handler = null;
public static void AcceptCallback(IAsyncResult ar)
{
  //Accept incoming connection
  Socket listener = (Socket)ar.AsyncState;
  handler = listener.EndAccept(ar);
}

handlerクライアントがソケットから切断されたことをできるだけ早く発見する方法を見つける必要があります。

私はもう試した:

  1. handler.Available;
  2. handler.Send(new byte[1], 0, SocketFlags.None);
  3. handler.Receive(new byte[1], 0, SocketFlags.None);

上記のアプローチは、サーバーに接続していて、サーバーがいつ切断されたかを検出したい場合には機能しますが、サーバーであり、クライアントの切断を検出したい場合には機能しません。

どんな助けでも大歓迎です。

4

15 に答える 15

2

私は非常に便利であることがわかりました。そのための別の回避策です!

ネットワークソケットからデータを読み取るために非同期メソッドを使用する場合 (つまり、BeginReceive-EndReceive メソッドを使用します)、接続が終了するたびに; これらの状況のいずれかが表示されます: メッセージがデータなしで送信される ( Socket.Available- で表示できますBeginReceiveが、トリガーされても値はゼロになります)、またはSocket.Connectedこの呼び出しで値が false になります (その場合は使用しないでくださいEndReceive)。

私が使用した関数を投稿しています。それから私が何を意味したかをよりよく理解できると思います:


private void OnRecieve(IAsyncResult parameter) 
{
    Socket sock = (Socket)parameter.AsyncState;
    if(!sock.Connected || sock.Available == 0)
    {
        // Connection is terminated, either by force or willingly
        return;
    }

    sock.EndReceive(parameter);
    sock.BeginReceive(..., ... , ... , ..., new AsyncCallback(OnRecieve), sock);

    // To handle further commands sent by client.
    // "..." zones might change in your code.
}
于 2010-01-06T19:18:49.913 に答える
2

これは私にとってはうまくいきました。重要なのは、ポーリングでソケットの状態を分析するために別のスレッドが必要なことです。ソケットと同じスレッドで実行すると、検出に失敗します。

//open or receive a server socket - TODO your code here
socket = new Socket(....);

//enable the keep alive so we can detect closure
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);

//create a thread that checks every 5 seconds if the socket is still connected. TODO add your thread starting code
void MonitorSocketsForClosureWorker() {
    DateTime nextCheckTime = DateTime.Now.AddSeconds(5);

    while (!exitSystem) {
        if (nextCheckTime < DateTime.Now) {
            try {
                if (socket!=null) {
                    if(socket.Poll(5000, SelectMode.SelectRead) && socket.Available == 0) {
                        //socket not connected, close it if it's still running
                        socket.Close();
                        socket = null;    
                    } else {
                        //socket still connected
                    }    
               }
           } catch {
               socket.Close();
            } finally {
                nextCheckTime = DateTime.Now.AddSeconds(5);
            }
        }
        Thread.Sleep(1000);
    }
}
于 2015-07-28T03:08:33.077 に答える
1

http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.connected.aspxのコード例 は、データを送信せずにソケットがまだ接続されているかどうかを判断する方法を示しています。

サーバー プログラムで Socket.BeginReceive() を呼び出した後、クライアントが接続を「適切に」閉じた場合、受信コールバックが呼び出され、EndReceive() は 0 バイトを返します。これらの 0 バイトは、クライアントが切断された可能性があることを意味します。その後、MSDN のサンプル コードに示されている手法を使用して、接続が閉じられたかどうかを確認できます。

于 2011-01-02T03:36:28.287 に答える
0

メソッド SetSocketOption を使用すると、Socket が切断されるたびに通知する KeepAlive を設定できます。

Socket _connectedSocket = this._sSocketEscucha.EndAccept(asyn);
                _connectedSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, 1);

http://msdn.microsoft.com/en-us/library/1011kecd(v=VS.90).aspx

それが役に立てば幸い!ラミロ・リナルディ

于 2011-01-05T13:24:38.627 に答える
0

セレクトしか使えないの?

接続されたソケットで select を使用します。select がソケットを Ready として返すが、その後の Receive が 0 バイトを返す場合は、クライアントが接続を切断したことを意味します。私の知る限り、これがクライアントが切断されたかどうかを判断する最速の方法です。

私は C# を知らないので、私のソリューションが C# に適合しない場合 (C# はselectを提供します)、またはコンテキストを誤解した場合は無視してください。

于 2009-06-30T13:50:29.793 に答える