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

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

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

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

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

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

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

5 ответов


Я не думаю, что это возможно для одного экземпляра ServerSocket для прослушивания нескольких портов. Вы можете, конечно, иметь несколько ServerSockets. Однако, как вы уже знаете,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

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

мы собираемся использовать селектор для выбора готовности и 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 пакет для создания неблокирующего асинхронного сервера, который может прослушивать несколько портов.


вы не можете послушать все порты, но вы можете слушать их. Создать один ServerSocket ( http://download.oracle.com/javase/6/docs/api/java/net/ServerSocket.html#ServerSocket%28int%29) для каждого порта, который вы хотите прослушать, и принимать соединения на каждом.


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

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


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

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