public static void main(String[] args) throws Exception { // Crear un ServerSocketChannel ServerSocketChannel servidor = ServerSocketChannel.open(); servidor.bind(new InetSocketAddress(5555)); servidor.configureBlocking(false); // Configurar como no bloqueante
// Crear un selector y registrar el evento de aceptación
Selector selector = Selector.open();
servidor.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
selector.select(2000); // Esperar eventos durante 2000 ms
Set<SelectionKey> clavesSeleccionadas = selector.selectedKeys();
Iterator<SelectionKey> iterador = clavesSeleccionadas.iterator();
while (iterador.hasNext()) {
SelectionKey clave = iterador.next();
if (clave.isAcceptable()) {
SocketChannel cliente = servidor.accept();
cliente.configureBlocking(false);
System.out.println("Cliente conectado desde: " + cliente.getRemoteAddress());
cliente.register(selector, SelectionKey.OP_READ);
} else if (clave.isReadable()) {
SocketChannel canal = (SocketChannel) clave.channel();
ByteBuffer buffer = ByteBuffer.allocate(32);
int bytesLeidos = canal.read(buffer);
if (bytesLeidos == -1) {
clave.cancel();
System.out.println("Cliente desconectado");
continue;
}
buffer.flip();
String mensaje = StandardCharsets.UTF_8.decode(buffer).toString();
System.out.println("Mensaje recibido del cliente: " + mensaje);
}
iterador.remove();
}
}
}
Y aquí está el código para un cliente utilizando Java NIO:
private static void enviarConNIO() throws Exception { SocketChannel cliente = SocketChannel.open(); cliente.configureBlocking(false); InetSocketAddress direccion = new InetSocketAddress("127.0.0.1", 5555);
if (!cliente.connect(direccion)) {
while (!cliente.finishConnect()) {
System.out.println("Conectando... por favor, espere.");
}
}
ByteBuffer mensaje = ByteBuffer.wrap("Prueba de mensaje. qwertyuikl1234567890123456789123123456789!!!!".getBytes(StandardCharsets.UTF_8));
cliente.write(mensaje);
Thread.sleep(60000);
cliente.close();
}
Esta implementación utiliza un solo reactor para manejar todos los eventos, incluyendo conexiones y lecturas/escrituras. Sin embargo, en aplicaciones más complejas, se pueden utilizar múltiples reactores, donde un reactor principal se encarga de las conexiones y los reactores secundarios manejan las lecturas y escrituras, posiblemente delegando estas tareas a un grupo de subprocesos.</div>