4

「The Rox Java NIO Tutorial」の Java NIO (ノンブロッキング) に基づくサーバー側コードを使用しようとしています。多くの受信ソケット接続があり、100 のみを受け入れたいと考えています。したがって、100 のアクティブな接続がある場合、新しい接続は拒否/拒否する必要があります。しかし、それを行う方法は?SocketChannel オブジェクトを返すメソッド ServerSocketChannel.accept() のみがあります。そのオブジェクトを使用して socketChannel.socket().close() を呼び出すことができますが、接続は既に開いています。コードの一部を次に示します。

@Override
public void run() {
    while (true) {
        try {
            // Wait for an event one of the registered channels
            this.selector.select();

            // Iterate over the set of keys for which events are available
            Iterator selectedKeys = this.selector.selectedKeys().iterator();
            while (selectedKeys.hasNext()) {
                SelectionKey key = (SelectionKey) selectedKeys.next();
                selectedKeys.remove();

                if (!key.isValid()) {
                    continue;
                }

                // Check what event is available and deal with it
                if (key.isAcceptable()) {
                    this.accept(key);
                } else if (key.isReadable()) {
                    this.read(key);
                } else if (key.isWritable()) {
                    this.write(key);
                }
            }
        } catch (Exception e) {
            logger.warn("Reading data", e);
        }
    }
}

そしてaccept()メソッド:

 private void accept(SelectionKey key) throws IOException {
    // For an accept to be pending the channel must be a server socket channel.
    ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel();

    // Accept the connection and make it non-blocking        
    if (noOfConnections < MAX_CONNECTIONS) {
        SocketChannel socketChannel = serverSocketChannel.accept();
        Socket socket = socketChannel.socket();
        socket.setKeepAlive(true);
        socketChannel.configureBlocking(false);
        // Register the new SocketChannel with our Selector, indicating
        // we'd like to be notified when there's data waiting to be read
        socketChannel.register(this.selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);//listener for incoming data: READ from client, WRITE to client
        noOfConnections++;
        logger.info("Accepted: " + socket.getRemoteSocketAddress().toString());
    } else {

        // REJECT INCOMING CONNECTION, but how?

        logger.warn("Server is full: " + noOfConnections + " / " + MAX_CONNECTIONS);
    }
}

接続が受け入れられない場合、accept() メソッドが何度も呼び出されています。

手伝ってくれてありがとう!

4

3 に答える 3

1

それを達成する方法はありませんが、それがあなたが本当に望んでいること、または少なくともあなたが本当にすべきことであるとは思えません。

接続の受け入れを停止する場合は、サーバー ソケット チャネルの選択キーの InterestOps を 0 に変更しOP_ACCEPT、再び受け入れる準備ができた時点に戻します。その間、isAcceptable()決して真実ではないので、あなたが説明した問題は発生しません。

ただし、それによりそれ以上の接続が拒否されることはありません。私の意見と TCP の設計者の意見では、それらが属しているバックログ キューにそれらが残されるだけです。バックログ キューがいっぱいになると、別の障害動作が発生します。クライアントでの影響はシステムに依存します。接続の拒否やタイムアウトです。

于 2013-01-29T15:58:30.140 に答える