0

準備ができているチャネルごとにメッセージを決定して送信できる通常の方法でセレクターを使用する代わりに、現在準備ができている接続を選択してそこにメッセージを送信したいと思います。

おそらくこれは、すべてのチャネルを読み取り用のセレクターに投入し、それらが出てきたら読み取りの準備ができているとマークし、次に書き込み用に同じことを行い、準備ができているとマークしたものの中から選択することで実行できます。

これは良い考えですか、これを行うためのより良い方法はありますか、何に注意する必要がありますか? たとえば、Rox チュートリアルには、 「OP READ と OP WRITE を混在させようとすると、すぐに問題が発生します。これを行うと、Sun Windows の実装がデッドロックすることが確認されています。」と記載されています。ここに同様の落とし穴はありますか?実装する最良の方法は何ですか:

boolean isReadyForRead(SocketChannel c);
boolean isReadyForWrite(SocketChannel c);
4

2 に答える 2

6

セレクターがウェイクアップしたときに、SelectionKeyを使用して、ソケットが読み取りまたは書き込みの準備ができているかどうかを確認する必要があります。

これは、 NIOサーバーとクライアントの作成に関する非常に便利なチュートリアルですhttp://rox-xmlrpc.sourceforge.net/niotut/

于 2009-09-20T16:07:34.823 に答える
2

このようなものはどうですか?

public static boolean isReadyForRead(SocketChannel socket) throws IOException {
    return isReady(socket, SelectionKey.OP_READ);
}

public static boolean isReadyForWrite(SocketChannel socket) throws IOException {
    return isReady(socket, SelectionKey.OP_WRITE);
}

public static boolean isReady(SocketChannel socket, int op) throws IOException {
    // Setup
    if (socket.isBlocking()) 
        throw new IllegalArgumentException("Socket must be in non-blocking mode");

    Selector selector = SelectorProvider.provider().openSelector();
    socket.register(selector, op);

    // Real work
    if (selector.selectNow() == 0)
        return false;
    // Just in case selector has other keys
    return selector.selectedKeys().contains(socket.keyFor(selector));
}

この呼び出しは毎回セットアップを行うため、非常に非効率的です。囲んでいるクラスがある場合は、これを移動する必要があります。セレクターにキーが 1 つしか含まれていないことがわかっている場合は、最後の行を " return true;" に変更できます。

私はただの楽しみのためにこれをやっています。これが役立つシナリオは考えられません。Select() は、ソケットのステータスを効率的に通知するように設計されており、誰もがそれを直接使用する必要があります。

于 2009-09-20T19:25:04.127 に答える