Как я могу постараться не блокироваться с Java ServerSocket?

Я работаю над слушателем сокета, который должен послушать на 2 портах для 2 типов данных (порт 80 и порт 81). Эти данные очень похожи как в виде операций, которые выполняются на данных и просто отличаются, потому что они прибывают n различные порты. Я шел вперед и кодировал реализацию с помощью класса ServerSocket Java, только чтобы понять позже, что принятие () метод класса ServerSocket является блоком, и мой наклон реализации предоставляют это. Таким образом, теперь я думал о реализации той же NIO Java использования, но пройдя некоторые учебные руководства я думаю, что я более смущен, чем, как я запустил. Было бы замечательно, если кто-то здесь мог бы обойти меня посредством целого процесса, даже его быть в псевдо коде или законе, техническом, "что сделать затем". Это - то, чего я планирую достигнуть.

Послушайте, как навсегда на 2 портах путем вызова 2 подобных потоков. (не блокирующийся) удаленное устройство от некоторых сетевых подключений местоположения, отправляет данные и затем разъединяется.

Я думаю, говорит ли только знание того, как NIO может использоваться для установки сервера для слушания на порте, что порт 80, на localhost, достигается, остальное все довольно легко реализовать.

Удачи

13
задан erickson 29 May 2015 в 17:07
поделиться

3 ответа

NIO требуется, когда необходимо масштабировать до многих тысяч одновременных подключений.

В противном случае я бы предложил использовать несколько потоков. Для каждого порта (и соответствующего ему ServerSocket ) создайте поток, который вызывает accept () в цикле. Эти вызовы будут блокироваться, но это нормально, потому что другие потоки работают, заботясь о любых доступных задачах.

Когда новый сокет принят, создайте еще один поток, выделенный для этого соединения. Это зависит от приложения, но обычно этот поток будет читать из сокета (операция блокировки) и выполнять запрошенную операцию, записывая результаты обратно в сокет.

Эта архитектура масштабируется до многих сотен подключений на большинстве настольных платформ. И модель программирования довольно проста, если каждое соединение является автономным и независимым от других (это позволяет избежать проблем с параллелизмом). Внедрение NIO обеспечит большую масштабируемость, но потребует большой сложности.

7
ответ дан 1 December 2019 в 20:29
поделиться

Вот небольшой пример, чтобы начать работу с NIO.

Это сервер, слушающий порты 80 и 81 и печати все, что получено на стандартном выходе. Соединение закрывается после получения пакета, начиная с закрытия ; Весь сервер выключен после получения пакета, начиная с Quit . Отсутствует от отправки детали и обработки ошибок может быть немного лучше. : -)

public static void main() throws IOException {
    ByteBuffer buffer = ByteBuffer.allocate(1024);
    Selector selector = Selector.open();

    ServerSocketChannel server1 = ServerSocketChannel.open();
    server1.configureBlocking(false);
    server1.socket().bind(new InetSocketAddress(80));
    server1.register(selector, OP_ACCEPT);

    ServerSocketChannel server2 = ServerSocketChannel.open();
    server2.configureBlocking(false);
    server2.socket().bind(new InetSocketAddress(81));
    server2.register(selector, OP_ACCEPT);

    while (true) {
        selector.select();
        Iterator<SelectionKey> iter = selector.selectedKeys().iterator();
        while (iter.hasNext()) {
            SocketChannel client;
            SelectionKey key = iter.next();
            iter.remove();

            switch (key.readyOps()) {
                case OP_ACCEPT:
                    client = ((ServerSocketChannel) key.channel()).accept();
                    client.configureBlocking(false);
                    client.register(selector, OP_READ);
                    break;
                case OP_READ:
                    client = (SocketChannel) key.channel();
                    buffer.clear();
                    if (client.read(buffer) != -1) {
                        buffer.flip();
                        String line = new String(buffer.array(), buffer.position(), buffer.remaining());
                        System.out.println(line);
                        if (line.startsWith("CLOSE")) {
                            client.close();
                        } else if (line.startsWith("QUIT")) {
                            for (SelectionKey k : selector.keys()) {
                                k.cancel();
                                k.channel().close();
                            }
                            selector.close();
                            return;
                        }
                    } else {
                        key.cancel();
                    }
                    break;
                default:
                    System.out.println("unhandled " + key.readyOps());
                    break;
            }
        }
    }
}

SAB : поля Selectionkey ( op_accept ...) статически импортируется:

import static java.nio.channels.SelectionKey.*;
15
ответ дан 1 December 2019 в 20:29
поделиться

Многие платформы, такие как Apache MINA и Netty , были реализованы на основе Java NIO для повышения неблокирующего программирования ввода-вывода. Я настоятельно рекомендую им сделать ваше программирование NIO радостью, а не кошмаром. Они подходят под вашу проблему.

Кроме того, попробуйте использовать эффективный протокол как с точки зрения размера транспортного сообщения, так и с точки зрения производительности кодирования / декодирования (сериализации / десериализации). Google Protocol Buffers - надежное решение в этой области. Также посмотрите Kryo и KryoNet . Они могут быть полезны.

8
ответ дан 1 December 2019 в 20:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: