Сервер Java - несколько портов?

Я собираюсь запрограммировать сервер, но мне интересно, возможно ли то, что я имею в виду. Моя программа будет выводиться на несколько клиентов на нескольких портах - к каждому порту можно обращаться несколькими клиентами.

Обычно я бы использовал поточный сервер сокетов, но в этом случае мне нужно, чтобы он работал для нескольких портов. Использование, которое я имею в виду, находится в неопределенном псевдокоде ниже:

  • Запустить сервер
  • Прослушивание входящих соединений на нескольких портах
  • Определите порт, подключенный к
    • Если порт 1, запустите поток, который прослушивает клиент и выводит тип сообщения x
    • Если порт 2, запустите поток, который прослушивает клиент и выводит тип сообщения y

Надеюсь, это имеет смысл, и вы можете видеть, что я пытаюсь сделать. Проще говоря: прослушивание выбранных портов, создание потокового соединения сокетов на основе того, к какому порту подключен.

Является ли это вообще выполнимым, или я собираюсь завершить многопоточные поточные серверы сокетов?

Изменить: Изменена формулировка, чтобы лучше отразить этот вопрос.

Ответ 1

Я не думаю, что для одного экземпляра ServerSocket можно прослушивать несколько портов. Конечно, вы можете иметь несколько ServerSocket s. Однако, как вы уже знаете, ServerSocket.accept блокирует.

Вместо этого вы можете использовать ServerSocketChannel. Они используются аналогичным образом, но не блокируются.

Если нет ожидающих соединений при вызове ServerSocketChannel.accept, то он просто возвращает null.

Вы можете использовать с Selector, который принимает набор каналов и блоков, пока хотя бы один из них не будет иметь ожидающее соединение.

Я не помню, как их использовать, но этот кажется достойным примером кода.

edit: Вот мой собственный пример (псевдо-иш)

Selector selector = Selector.open();

int[] ports = {4000,4001,6000};

for (int port : ports) {
   ServerSocketChannel server = ServerSocketChannel.open();
   server.configureBlocking(false);

   server.socket().bind(new InetSocketAddress(port));
// we are only interested when accept evens occur on this socket
   server.register(selector, SelectionKey.OP_ACCEPT); 
}

while (selector.isOpen()) {
   selector.select();
   Set readyKeys = selector.selectedKeys();
   Iterator iterator = readyKeys.iterator();
   while (iterator.hasNext()) {
      SelectionKey key = (SelectionKey) iterator.next();
      if (key.isAcceptable()) {
         SocketChannel client = server.accept();
         Socket socket = client.socket();
// create new thread to deal with connection (closing both socket and client when done)
      }
   }
}

// tidy up selector and channels

Ответ 2

Привет, так что позвольте мне понять это прямо. Что вы хотите сделать, так это создать сервер, который может прослушивать несколько портов, и когда вы получите новое соединение, вы хотите узнать, какой порт использует это соединение, правильно ли это? В этом случае вы можете сделать это очень легко с помощью пакета java.nio.

Мы собираемся использовать Selector для выбора готовности и ServerSocketChannel для слушать входящие соединения.

Сначала нам нужно объявить наш Selector.

Selector selector = Selector.open();

Теперь давайте создадим список портов для прослушивания и прослушивания на них.

int ports[] = new int[] { 1234, 4321 };

// loop through each port in our list and bind it to a ServerSocketChannel
for (int port : ports) {
    ServerSocketChannel serverChannel = ServerSocketChannel.open();
    serverChannel.configureBlocking(false);
    serverChannel.socket().bind(new InetSocketAddress(port));
    serverChannel.register(selector, SelectionKey.OP_ACCEPT);
}

Теперь для процесса обработки SelectionKey.

while (true) {
    selector.select();

    Iterator<SelectionKey> selectedKeys = selector.selectedKeys().iterator();
    while (selectedKeys.hasNext()) {
        SelectionKey selectedKey = selectedKeys.next();

        if (selectedKey.isAcceptable()) {
            SocketChannel socketChannel = ((ServerSocketChannel) selectedKey.channel()).accept();
            socketChannel.configureBlocking(false);
            switch (socketChannel.socket().getPort()) {
                case 1234:
                    // handle connection for the first port (1234)
                    break;
                case 4321:
                    // handle connection for the secon port (4321)
                    break;
            }
        } else if (selectedKey.isReadable()) {
            // yada yada yada
        }
    }
}

Возможно, оператор switch не нужен для такой простой задачи, но для удобства чтения и понимания.

Помните, что этот сервер настроен неблокирующим асинхронным способом, так что все вызовы ввода-вывода, которые вы выполняете, не будут блокировать текущий поток. Поэтому НЕ НЕ инициировать новые потоки в процессе обработки SelectionKey.

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

Ответ 4

Я не думаю, что вы можете слушать все порты, нет. Это будет довольно дорого для ОС, чтобы реализовать, так что просто не так, как работает прослушивание портов.

Что делать, если несколько приложений одновременно прослушивали все "все" порты, к какому приложению должна была доставляться входящая пакетная сеть?

Ответ 5

Это должно быть возможно с NIO, однако я не вижу достаточной причины избегать использования одного потока на слушателя, если у вас не более 1K-порта.

Вам действительно нужно несколько портов для прослушивания? В большинстве случаев один порт может поддерживать все виды клиентов и указывать клиенту сервер (или сервер определяет, какой тип соединения необходим).