threads thread socket multithreaded multiples multiple clients clientes java multithreading tcp serversocket

thread - sockets java multiples clientes



Servidor Java-¿Varios puertos? (5)

Esto debería ser posible con NIO, sin embargo, no veo una buena razón para evitar tener un hilo por escucha a menos que tenga más de 1K de puerto.

¿Realmente necesitas múltiples puertos de escucha? En la mayoría de los casos, debería ser posible que un puerto admita todo tipo de clientes y haga que el cliente le indique al servidor (o al servidor que determine qué tipo de conexión se necesita).

Estoy a punto de programar un servidor, pero me pregunto si lo que tengo en mente es posible. Mi programa se enviará a múltiples clientes en múltiples puertos; a cada puerto pueden acceder varios clientes.

Normalmente usaría un servidor de socket con rosca, pero en este caso lo necesito para múltiples puertos. El uso que tengo en mente está en un pseudocódigo vago a continuación:

  • Inicie el servidor
  • Escuche las conexiones entrantes en varios puertos
  • Identifique el puerto que está conectado a
    • Si es el puerto 1, inicie un hilo escuchando al cliente y enviando el tipo de mensaje x
    • Si es el puerto 2, inicie un hilo escuchando al cliente y generando un tipo de mensaje y

Espero que tenga sentido y puedas ver lo que estoy tratando de hacer. En pocas palabras: escuche los puertos seleccionados, cree una conexión de socket con rosca según el puerto al que se está conectando.

¿Esto es factible, o voy a terminar con servidores de socket con subprocesos múltiples?

Editar: modificó la redacción para reflejar mejor la pregunta.


No creo que puedas escuchar todos los puertos, no. Sería bastante caro para el sistema operativo implementarlo, así que simplemente no es así como funciona la escucha del puerto.

¿Qué sucede si varias aplicaciones están escuchando simultáneamente "todos" los puertos, a qué aplicación debe el subsistema de red entregar los paquetes entrantes?


No creo que sea posible para una sola instancia de ServerSocket escuchar múltiples puertos. Por supuesto, puede tener varios ServerSocket s. Sin embargo, como ya sabes, ServerSocket.accept bloquea.

Lo que puede usar en su lugar es un ServerSocketChannel . Se usan de manera similar, pero no bloquean.

Si no hay conexiones pendientes cuando se ServerSocketChannel.accept , simplemente devuelve null.

Puede usarlo con un Selector que toma un conjunto de canales y bloques hasta que al menos uno tenga una conexión pendiente.

No recuerdo los detalles sobre cómo usarlos, pero este parece ser un ejemplo de código decente.

editar: Aquí está mi propio ejemplo (pseudo-ish)

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



Hola , déjame aclarar esto. Lo que quiere hacer es crear un servidor que pueda escuchar en múltiples puertos y cuando obtenga una nueva conexión, querrá saber qué puerto utilizó esa conexión, ¿es correcto? Bueno, si ese es el caso, puedes hacer esto muy fácilmente con el uso del paquete java.nio .

Vamos a usar un Selector para la selección de preparación y un ServerSocketChannel para escuchar las conexiones entrantes.

Primero debemos declarar nuestro Selector .

Selector selector = Selector.open();

Ahora permitamos crear una lista de puertos para escuchar y comenzar a escucharlos.

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); }

Ahora para el proceso de manejo 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 } } }

Quizás una declaración de cambio no sea necesaria para una tarea tan simple, pero es para facilitar la lectura y la comprensión.

Recuerde, este servidor está configurado de forma asíncrona sin bloqueo para que todas las llamadas de E / S que realice no bloqueen el hilo actual. Así que NO inicie ningún hilo nuevo en el proceso de manejo SelectionKey .

Además, sé que esto no responde completamente a su pregunta (podría ser que no), pero de hecho le dará una comprensión sobre cómo usar el paquete java.nio para crear un servidor asíncrono sin bloqueo que pueda escuchar en puertos múltiples