Coverage Summary for Class: ClientHandler (it.polimi.ingsw.gc14.Network.TCP.Server)
| Class |
Class, %
|
Method, %
|
Branch, %
|
Line, %
|
| ClientHandler |
0%
(0/1)
|
0%
(0/6)
|
0%
(0/14)
|
0%
(0/31)
|
package it.polimi.ingsw.gc14.Network.TCP.Server;
import it.polimi.ingsw.gc14.LimitedMap;
import it.polimi.ingsw.gc14.Model.MiniModel;
import it.polimi.ingsw.gc14.Network.NetworkEvent;
import it.polimi.ingsw.gc14.Network.NetworkEvents.DisconnectedPlayer;
import java.io.*;
import java.net.*;
import java.util.List;
import java.util.concurrent.BlockingQueue;
/**
* Handles the TCP connection with a single client.
* Each instance runs on a dedicated thread and is responsible for receiving {@link NetworkEvent} from its client and adding them
* to the {@link #actionQueue}.
* It is also responsible to send events and game model updates back to the client.
*/
public class ClientHandler implements Runnable {
/**
* The username of the connected client on this handler
*/
private final String username;
/** {@code true} while the handler is actively reading from the socket; set to {@code false} on disconnect. */
private volatile boolean running;
/**
* Returns the username associated with this client.
*
* @return the username associated with this client.
*/
public String getUsername() {
return username;
}
/** The TCP socket */
private final Socket clientSocket;
/** Input stream used to receive objects from the client */
private final ObjectInputStream in;
/** Output stream used to send objects to the client */
private final ObjectOutputStream out;
/**
* Shared list of all client handlers.
* This handler removes itself from the list when disconnected.
*/
private final List<ClientHandler> clientHandlers;
/** Maps each connected player's username to their connection state (true = connected). */
private final LimitedMap<String, Boolean> limitedMap;
/** Queue containing the events to be applied to the game model */
private final BlockingQueue<NetworkEvent> actionQueue;
/**
* Class constructor that initializes the attributes.
*
* @param username the username associated with the client.
* @param clientSocket the socket representing the client's TCP connection.
* @param out the output stream used to send data to the client.
* @param in the input stream used to receive data from the client.
* @param clientHandlers the shared list of all active client handlers.
* @param playersMap the shared map containing the connected players.
* @param actionQueue the queue containing incoming events.
*/
public ClientHandler(String username, Socket clientSocket, ObjectOutputStream out, ObjectInputStream in, List<ClientHandler> clientHandlers, LimitedMap<String,Boolean> playersMap, BlockingQueue<NetworkEvent> actionQueue) {
this.username=username;
this.clientSocket = clientSocket;
this.in = in;
this.out = out;
this.clientHandlers = clientHandlers;
this.actionQueue = actionQueue;
this.limitedMap = playersMap;
}
/**
* Listens for incoming {@link NetworkEvent}s from the client and adds them to the {@link #actionQueue}.
* Upon disconnection, this handler removes itself from {@link #clientHandlers}.
*/
@Override
public void run() {
running = true;
try {
while (running) {
NetworkEvent event = (NetworkEvent) in.readObject();
if (!actionQueue.offer(event)) {
System.out.println("Error inserting action into queue");
}
}
} catch (IOException e) {
} catch (ClassNotFoundException e) {
System.err.println("Class not found: " + username);
} finally {
if (running) disconnect();
}
}
/**
* Sends a {@link NetworkEvent} to the client.
* @param event The network event to send to the client.
*/
public synchronized void notifyEvent(NetworkEvent event) {
try {
out.reset();
out.writeObject(event);
} catch (IOException e) {
e.printStackTrace();
disconnect();
}
}
/**
* Sends the current game model to this client.
* @param game The current state of the game to send to the client.
*/
public synchronized void notifyMiniModel(MiniModel game) {
try {
out.reset();
out.writeObject(game);
} catch (IOException e) {
e.printStackTrace();
disconnect();
}
}
/**
* Disconnects the client from the server.
*
* <p>The client handler is stopped and removed from the list of active handlers.
* The player is marked as disconnected, a {@link DisconnectedPlayer} event is
* added to the action queue, and the associated socket is closed.
*/
public synchronized void disconnect() {
if (!running) return;
running = false;
clientHandlers.remove(this);
limitedMap.put(username, false);
actionQueue.add(new DisconnectedPlayer(username));
System.err.println("(TCP) Disconnected player: " + username);
try { clientSocket.close(); } catch (IOException ignored) {}
}
}