Java Server - несколько портов? - PullRequest
       32

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

11 голосов
/ 22 февраля 2011

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

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

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

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

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

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

Ответы [ 5 ]

15 голосов
/ 22 февраля 2011

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

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

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

Вы можете использовать с 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
9 голосов
/ 22 марта 2011

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

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

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

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

1 голос
/ 22 февраля 2011

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

0 голосов
/ 22 февраля 2011

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

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

0 голосов
/ 22 февраля 2011

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...