以前C#の非同期TCPサーバのサンプルを作った時はBeginxxxメソッドを使用したサンプルコードを作成しましたが、今回はxxxAsyncを使ったTCPサーバを作成してみます。
きっかけは調べ物をしていた時に偶然にxxxAsyncメソッドを見つけ、何が違うのか調べたらxxxAsyncの方が良いようなコメント(英文)が幾つか見つかったので近々に使用する事はないが、突然使う事になった時のために覚えておこうと思ったからです。
前回の解説は
今回は参考になる日本語の情報も少なく間違えがあるかもしれませんので間違えがありましたらご指摘お願いします。
サンプルコードはこちら
プログラムの全体像としては接続待ちのAcceptAsyncメソッドをWhileループで常に接続待ちとさせメソッドが実行されたら送受信するクライアント毎にインスタンスを生成し、そこでクライアントとのやり取りを行います。
TCPクライアントから0バイトのデータ受信または任意に切断したらSocketAsyncEventArgsを破棄して終了となります。
SocketAsyncEventArgs
このクラスを用いて非同期通信を行います。
インスタンスのイベントハンドラにイベント発生時のメソッドを定義したり送受信バッファの設定を行います。
1つのTCPクライアントに1つのSocketAsyncEventArgsインスタンスが割り当てられます。
終了時には破棄する必要がありますので相手から切断された時や自分で切断した時は破棄を忘れないでください。
AcceptAsync
TCPクライアントの接続待ちを非同期で行います。
非同期とは言え戻り値がfalseの場合、同期的にクライアント接続が行われるので戻り値によって少し処理を変える必要があります。
非同期で処理された場合Completedイベントに加えられたイベントハンドラが実行されます。
上記サンプルでは非同期で処理が行こなわれたらManualResetEventSlimがSetされるまで待ちます。
イベントハンドラは
LastOperationを参照する事でどのようなイベントが発生したかを判断できます。
ReceiveAsync
非同期受信です。
これもAcceptAsyncと同様に戻り値がtrueの場合は非同期に、falseの場合は同期的に処理が行われた事を示します。
但し、非同期であれ同期的であれ同じ入れ物に受信データが入るので戻り値がtrueの場合、イベントハンドラでManualResetEventSlimがSetされるのを待つだけで大丈夫です。
データを受信すると「args.BytesTransferred」に受信したデータ数を表します。
これはBeginReceiveと同様ですが受信データ量が0ならクライアントが切断したと判断できます。
イベントハンドラは
LastOperationでセットするManualResetEventSlimを変えてますが、上手くやれば1つでもいいかもしれません。
SendAsync
非同期送信です。
これも同様に戻り値がfalseなら同期的に処理が完了、trueなら非同期に処理が完了した事を示します。
これもReceiveAsyncと同じ考えで戻り値がfalseでもtrueでも特段処理は変わらすtrueならManualResetEventSlimがSetされるのを待つだけです。
ちなみに任意の切断は
で可能です。
0 件のコメント:
コメントを投稿