0

Java NIO を使用しようとしています。エミュレーターがインターネットにアクセスできないときに接続をテストしようとするまで、すべて問題ありませんでした。そしてここで次の結果:

2.2 では、select() が 1 つのキーを選択し、その後、finishConnect() 呼び出しが例外をスローします。予想通り。ただし、最初の行がコメント解除されている場合にのみ機能します (preferIPv6 = false)。

しかし、4.1.2 では select() は常にゼロを返します。選択されたキー セットは空です。値を調べると、選択キーは常に操作の準備ができておらず、interestOps は 8 (OP_CONNECT) です。

java connect() 呼び出しで IOException: Network is unreachable をスローします。予想通り。

私が間違っていることと、select() をブロックさせる方法は?

//System.setProperty("java.net.preferIPv6Addresses", "false");

try {
    Selector selector = Selector.open();

    SocketChannel socketChannel = SocketChannel.open();

    socketChannel.configureBlocking(false);

    boolean connected = socketChannel.connect(new InetSocketAddress("173.194.44.3", 80));

    SelectionKey selectionKey;

    if (connected) {
        selectionKey = socketChannel.register(selector, SelectionKey.OP_READ);
    } else {
        selectionKey = socketChannel.register(selector, SelectionKey.OP_CONNECT);
    }

    while (true) {
        int selected = selector.select();

        if (selected == 0) continue;

        for (SelectionKey key : selector.selectedKeys()) {
            if (socketChannel.finishConnect()) {
                key.interestOps(SelectionKey.OP_READ);
            }
        }

        selector.selectedKeys().clear();
    }
} catch (IOException e) {
    throw new RuntimeException("IOException", e);
}

ありがとう。

4

2 に答える 2

0

問題は解決可能に見えます。

OP_READ の関心が追加され、何らかの理由でセレクターがキーを選択したため、読み取りの準備が整いました。

しかし、読み込もうとすると NotYetConnectedException がスローされました。だから、私はこれをキャッチして処理することができます。次に、ブロックを選択します。

しかし、それはバグのように見えます。

try {
    Selector selector = Selector.open();

    SocketChannel socketChannel = SocketChannel.open();

    socketChannel.configureBlocking(false);

    boolean connected = socketChannel.connect(new InetSocketAddress("173.194.44.3", 80));

    SelectionKey selectionKey;

    int validOps = socketChannel.validOps();

    if (connected) {
        selectionKey = socketChannel.register(selector, SelectionKey.OP_READ);
    } else {
        selectionKey = socketChannel.register(selector, SelectionKey.OP_CONNECT | SelectionKey.OP_READ);
    }

    ByteBuffer buffer = ByteBuffer.allocate(512);

    while (true) {
        int selected = selector.select();

        if (selected == 0) continue;

        for (SelectionKey key : selector.selectedKeys()) {
            SocketChannel sc = (SocketChannel) key.channel();

            if ((key.interestOps() & SelectionKey.OP_CONNECT) != 0 && key.isConnectable())
            {
                if (socketChannel.finishConnect()) {
                    key.interestOps(SelectionKey.OP_READ);
                }
            }

            if (key.isReadable()) {
                while (true) {
                    int readed = 0;

                    try {
                        readed = sc.read(buffer);
                    } catch (Exception e) {
                        sc.close();
                    }

                    if (readed == 0) break;

                    if (readed == -1) throw new RuntimeException("Closed");
                }
            }
        }

        selector.selectedKeys().clear();
    }
} catch (IOException e) {
    throw new RuntimeException("IOException", e);
}

多分ここにもっと「非魔法」の解決策が存在しますか?

于 2013-08-12T14:25:42.497 に答える