1
Socket SocketSrv;
public static ManualResetEvent Done = new ManualResetEvent(false);
IPEndPoint IPP = new IPEndPoint(IPAddress.Any, 1234);

void Listening()
{
    SocketSrv = new Socket(AddressFamily.InterNetwork,
                           SocketType.Stream, ProtocolType.Tcp);
    try
    {
        SocketSrv.Bind(IPP);
        SocketSrv.Listen(5);

        while (true)
        {
            Done.Reset();
            info.Text = "Waiting for connections....";
            SocketSrv.BeginAccept(new AsyncCallback(Connection),
                                  SocketSrv);
            Done.WaitOne();
        }
    }
    catch(Exception error)
    {
        MessageBox.Show(error.Message);
    }
}

void Connection(IAsyncResult ar)
{
    Done.Set();
    Socket con= (Socket)ar.AsyncState;
    Socket handler = con.EndAccept(ar); 
}

私はManualResetEventそれを使用したことがないので、この非同期操作を理解しようとしています。

  • ステップ1。はSocketSrvTCP 接続を受け入れるように作成され、「コマンド」の送受信のタイプはストリームです。

  • ステップ2。ソケットは ip,port にバインドされ、接続のリッスンを開始します。

  • Step3. while ループ内:

    • はリセットです(これはブール型で、スレッドがビジーかどうかを示すクラスであるManualResetEventことを理解していManualResetEventます)。この場合、接続が確立され、別の接続が来ている場合、リセットする必要があるため、イベントは常にリセットされます再度「操作」を開始してください。

    • 非同期動作を開始しBeingAcceptている中で、実行されるコールバック関数とIAsyncResult「ソケット」となる引数。

  • Step4. ResetEvent現在、Waiting は現在のスレッドをブロックし、接続メソッドのハンドラーが終了するのを待っているため、現在の接続の初期化を完了できます。

  • Step5. 接続スレッドでResetEventは、シグナルを true に設定します。つまり、それが何を意味するのかわかりません。ResetEventメインスレッドのブロックを解除するように指示していると思います。

「con」ソケットでは、AsyncState. 私はそれが何を意味するのか分かりません。

ハンドラー ソケットResetEventで、接続が確立されたことを伝えます。

言われていることですが、誰かが私が言ったことが真実か間違っているか、そしてその理由を教えてもらえますか?

4

1 に答える 1

1

このイベントは、接続が発生したときに、メソッドが呼び出されるBeginAcceptまで再度呼び出されないようにするために使用されます。Connectたとえば、が呼び出される WaitOneまでスレッドを停止します。イベントの状態をシグナル状態に戻すために呼び出され、スレッドが再び停止し、再度呼び出されるのを待ちます。SetResetWaitOneConnect

個人的には、この特定のパターンは使用しません。このパターンのポイントの説明を見たことがありません。BeginAcceptループとConnectメソッドの間に何らかの共有状態があれば、それは理にかなっているかもしれません。しかし、書かれているように、イベントの使用によって状態が保護されることはありません。私が使用するときはBeginAccept、単純にイベントを使用しません。このようなコードを使用して、1 秒間に多くの接続を処理しました。イベントを使用しても、一度に接続が多すぎる場合のエラーを防ぐことはできません。率直に言って、非同期メソッドを使用して強制的に同期させることは、目的に反します。

AysncState観点からはBeginAccept、 は単に不透明なデータです。その特定の非同期操作に使用されるのは「状態」です。この「状態」はアプリケーション固有です。接続を非同期的に処理したい場合は、必要なものを何でも使用します。コールバックの場合、BeginAccept通常はサーバー ソケットを使用して何かを実行する必要があり、それが状態に渡されるため、呼び出すためにアクセスできますEndAcceptSocketSrvはメンバー フィールドであるため、実際にこれを行う必要はありません。代わり次のようにすることもできます。

SocketSrv.BeginAccept(new AsyncCallback(Connection), null);
//...
void Connection(IAsyncResult ar)
{
    Socket handler = SocketSrv.EndAccept(ar); 
    //...
}

あなたのコメントは、この特定のコードをよく理解していることを示しているようです。「Step4」は少しずれています。Connectionメソッドが終了するのを待っているのではなく、開始するのを待っています(Set最初の行として呼び出されるため)。はい、「Step5」は、Setブロックを解除することを意味するため、メインスレッドは次に をWaitOne呼び出します。ResetBeginAccept

于 2013-03-31T16:52:38.540 に答える