Servidor
Responsabilidades
- Aceptar conexiones TCP entrantes.
- Mantener y gestionar la lista de clientes conectados (
ClientListener). - Reenviar (broadcast) paquetes recibidos a los clientes pertinentes.
- Delegar la generación de IDs (a través de
Main) para jugadores y entidades. - Cerrar y limpiar conexiones de forma ordenada.
Puntos de entrada clave
src.net.Server— clase que ejecuta el listener del servidor en un hilo:- Constructor:
Server(GameScreen game, String ip, Integer port). run()— bucle principal que acepta conexiones y creaClientListener.sendAll(Object[] data, Integer id)— reenvía paquetes a todos los clientes, opcionalmente omitiendo elidremitente.-
close()— detiene el servidor y cierra todas las conexiones. -
src.net.ClientListener— represente una conexión cliente dentro del servidor: - Constructor:
ClientListener(Server server, Socket socket, Integer id). run()— procesa paquetes entrantes y los reenvía según la lógica de juego.send(Object[] data)— envía un paquete al cliente.close()/closeNoPacket()— limpian recursos y notifican desconexión.
Flujo de ejecución (alto nivel)
Main.startServer(ip, port)crea la instanciaServery la ejecuta en un hilo.Server.run()abre unServerSockety espera conexiones (accept).- Por cada conexión entrante se crea un
ClientListenercon un ID único y se ejecuta en un pool de hilos. - Los
ClientListenerreciben paquetes serializados (Object[]) desde el cliente y, según su tipo, realizan reenvíos o acciones específicas (p. ej. notificar nuevos jugadores, propagar posiciones o eventos del juego). - El servidor utiliza
sendAllpara difundir eventos a todos los clientes conectados salvo el origen cuando procede. - Al cerrar el servidor, se invocan
closeNoPacket()en los listeners y se liberan recursos.
Paquetes y responsabilidades relacionadas
CONNECTPLAYER→ el servidor asigna o registra el jugador y notifica a los demás conNEWPLAYER.GAMESTART→ difusión del inicio de la partida.ACTENTITYPOSITION,NEWENTITY,REMOVEENTITY→ sincronización de entidades entre clientes.ACTENEMY,ACTDAMAGEENEMY,ACTOTHERPLAYER,ACTBREAKBLOCK,ACTSCORE,ACTENTITYCOLOR→ eventos de juego reenviados a clientes.MESSAGE→ chat entre jugadores, retransmitido por el servidor.
Detalles de implementación
- Concurrencia: se usa un
ExecutorService(pool) para manejarClientListeneryCopyOnWriteArrayListpara la lista de usuarios. - Seguridad/validación: la implementación actual aplica un modelo "cliente primero"; no se validan los datos recibidos. Para servidores públicos se recomienda validar posiciones, límites de velocidad y tasas de mensajes.
- Robustez: en caso de error de E/S cada
ClientListenercierra su socket y el servidor elimina la referencia al usuario. - IDs:
Serversolicita IDs aMain(game.main.getIds()), por lo que la generación centralizada evita colisiones.
ClientListener
- Cada instancia maneja la comunicación con un cliente específico.
- Lee paquetes entrantes y los procesa según su tipo.
- Una vez procesados, reenvía los paquetes al servidor para su difusión a todos los demás clientes conectados.