Java NIO Selector не работает, когда не используется localhost - PullRequest
0 голосов
/ 18 сентября 2018

Я работал над программой, которая использует сетевое взаимодействие с Java и использует селектор NIO, следуя этому учебному пособию и по какой-то причине, когда я пытаюсь протестировать программу с моими друзьями (которые находятся далеко вдругой сети) он не работает, хотя, когда я пытаюсь проверить его самостоятельно только на моем компьютере, он работает отлично.
Вот соответствующий код вопроса:

Класс EchoServer (поток):

private Selector selector;
private ServerSocketChannel serverSocket;
private boolean stop = false;
private List<String> pendingStrings;

public EchoServer() throws IOException {
    // Get selector
    this.selector = Selector.open();
    System.out.println("Selector open: " + selector.isOpen());
    // Get server socket channel and register with selector
    this.serverSocket = ServerSocketChannel.open();
    InetSocketAddress hostAddress = new InetSocketAddress("", NetworkingSettings.PORT);
    serverSocket.bind(hostAddress);
    serverSocket.configur eBlocking(false);
    int ops = serverSocket.validOps();
    SelectionKey selectKy = serverSocket.register(selector, ops, null);
    this.pendingStrings = new ArrayList<>();
}

@Override
public void run() {
    while (!stop) {
        try {
            update();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

private void update() throws IOException {
    System.out.println("Waiting for select...");
    int noOfKeys = selector.select();

    System.out.println("Number of selected keys: " + noOfKeys);

    Set selectedKeys = selector.selectedKeys();
    Iterator iter = selectedKeys.iterator();

    while (iter.hasNext()) {

        SelectionKey ky = (SelectionKey) iter.next();
        if (ky.isAcceptable()) {
            acceptClient();
        }
        else if (ky.isReadable()) {
            readDataFromClient(ky);
        }
        iter.remove();
    }
}

Класс EchoClient:

private SocketChannel client;
private InetSocketAddress hostAddress;
private boolean connected;

public EchoClient(String ip) {
    this.hostAddress = new InetSocketAddress(ip, NetworkingSettings.PORT);
    connected = false;
}

public void connect() throws IOException {
    if (!connected) {
        client = SocketChannel.open(hostAddress);
        connected = true;
    }
}

public void sendMessage(String message) throws IOException {
    try {
        byte[] messageBytes = message.getBytes();
        ByteBuffer buffer = ByteBuffer.wrap(messageBytes);
        client.write(buffer);
        buffer.clear();
    } catch (IOException e) {
        cleanUp();
    }
}

Теперь, похоже, проблема в сервере, потому что я даже не могу подключиться к серверу, когда его запускает мой друг (а я - клиент).Я подозреваю, что источником проблемы являются эти строки в EchoServer :

InetSocketAddress hostAddress = new InetSocketAddress("", NetworkingSettings.PORT);
serverSocket.bind(hostAddress);

Но я не могу понять, что это такое.

Важное примечание: NetworkingSettings.PORT равно 80, я знаю, что это порт, используемый для http, и, возможно, в этом проблема, но я действительно хочу избежать необходимости использовать переадресацию портов и настройки брандмауэра.

1 Ответ

0 голосов
/ 19 сентября 2018

Проблема заключается в InetSocketAddress, с которым связывается ServerSocketChannel.Чтобы разрешить подключения как на локальном, так и на удаленном сетевых интерфейсах, вам необходимо привязаться к подстановочному адресу.Это делается с помощью конструктора InetSocketAddress , который принимает только номер порта:

InetSocketAddress hostAddress = new InetSocketAddress(NetworkingSettings.PORT);
...