0

JavaNIO2について。

クライアントのリクエストをリッスンするために次のものがあるとします...

asyncServerSocketChannel.accept(null, new CompletionHandler <AsynchronousSocketChannel, Object>() {
    @Override
    public void completed(final AsynchronousSocketChannel asyncSocketChannel, Object attachment) {
         // Put the execution of the Completeion handler on another thread so that 
         // we don't block another channel being accepted.
         executer.submit(new Runnable() {
             public void run() {
                 handle(asyncSocketChannel);
             }
         });

         // call another.
         asyncServerSocketChannel.accept(null, this);
     }

     @Override
     public void failed(Throwable exc, Object attachment) {
         // TODO Auto-generated method stub
     }
});

このコードは、クライアント接続プロセスを受け入れてから、別のコードを受け入れます。サーバーと通信するために、クライアントはAsyncSocketChannelを開き、メッセージを起動します。次に、完了ハンドラのcompleted()メソッドが呼び出されます。

ただし、これは、クライアントが同じAsyncSocketインスタンスで別のメッセージを送信したい場合は送信できないことを意味します。

別のAsycnSocketインスタンスを作成する必要があります。これは別のTCP接続を意味すると思いますが、これはパフォーマンスに影響します。

これを回避する方法はありますか?

または、別の言い方をすれば、同じasyncSocketChannelに複数のCompleteionHandlercompleted()イベントを受信させる方法はありますか?

編集:私の処理コードはこのようなものです...

public void handle(AsynchronousSocketChannel asyncSocketChannel) {
    ByteBuffer readBuffer = ByteBuffer.allocate(100);
    try {
        // read a message from the client, timeout after 10 seconds 
        Future<Integer> futureReadResult = asyncSocketChannel.read(readBuffer);
        futureReadResult.get(10, TimeUnit.SECONDS);
        String receivedMessage = new String(readBuffer.array());

        // some logic based on the message here...               

        // after the logic is a return message to client
        ByteBuffer returnMessage = ByteBuffer.wrap((RESPONSE_FINISHED_REQUEST + " " + client
                 + ", " + RESPONSE_COUNTER_EQUALS + value).getBytes());
        Future<Integer> futureWriteResult = asyncSocketChannel.write(returnMessage);
        futureWriteResult.get(10, TimeUnit.SECONDS);
   } ...

これで、サーバーは非同期チャネルからメッセージを読み取り、応答を返します。クライアントは、答えが得られるまでブロックします。しかし、これは大丈夫です。クライアントがブロックしてもかまいません。

これが終了すると、クライアントは同じ非同期チャネルで別のメッセージを送信しようとしますが、機能しません。

4

2 に答える 2

3

接続には2つのフェーズがあり、2つの異なる種類の完了ハンドラーがあります。最初のフェーズは接続要求を処理することです。これはあなたがプログラムしたものです(ジョナスが言ったようにBTW、別のエグゼキュータを使用する必要はありません)。2番目のフェーズ(複数回繰り返すことができます)は、I / O要求を発行し、要求の完了を処理することです。このためには、読み取りまたは書き込み用のデータを保持するメモリバッファを提供する必要があり、このためのコードは表示されませんでした。2番目のフェーズを実行すると、「クライアントが同じAsyncSocketインスタンスで別のメッセージを送信したい場合は送信できません」と書いたような問題がないことがわかります。

NIO2の問題の1つは、一方ではプログラマーが同じチャネルで同じ種類の複数の非同期操作(受け入れ、読み取り、または書き込み)を回避する必要があることです(そうでない場合はエラーが発生します)。ハンドラーで待機をブロックしないようにします。この問題は、 df4jアクターフレームワークのdf4j-nio2サブプロジェクトで解決されます。このサブプロジェクトでは、AsyncServerSocketChannelとAsyncSocketChannelの両方がアクターとして表されます。(df4jは私が開発したものです。)

于 2012-10-22T20:21:44.163 に答える
1

まず、completed-methodのようにエグゼキュータを使用しないでください。completed-methodは、新しいワーカースレッドですでに処理されています。

completed-method for.accept(...)で、を呼び出しasychSocketChannel.read(...)てデータを読み取る必要があります。クライアントは、同じソケットで別のメッセージを送信できます。completedこのメッセージは、おそらくサーバー上の別のワーカースレッドによって、-methodへの新しい呼び出しで処理されます。

于 2012-10-22T19:15:53.230 に答える