Call me Joni Mitchell because quit due to connection loss works on both sides now.

This commit is contained in:
Jonas 2022-04-07 12:29:36 +02:00
parent de69ea27bb
commit faa2b61acb
5 changed files with 45 additions and 17 deletions

View File

@ -6,7 +6,6 @@ import ch.unibas.dmi.dbis.cs108.multiplayer.helpers.ClientPinger;
import java.net.Socket;
import java.io.*;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Objects;
import java.util.Scanner;
@ -88,11 +87,12 @@ public class Client {
try {
chatMsg = in.readLine(); //todo: maybe if
if (chatMsg != null) {
parse(chatMsg); //todo: i think this trows an error BC chatMsg is null if client disconnects
}
parse(chatMsg);
} else { System.out.println("chatMsg is null");}
} catch (IOException e) {
//e.printStackTrace();
LOGGER.debug("Exception while trying to read message");
disconnectFromServer();
}
}
@ -102,7 +102,8 @@ public class Client {
}
/**
* Sends a message to the server, as is.
* Sends a message to the server, as is. The message has to already be protocol-formatted. ALL
* communication with the server has to happen via this method!
*
* @param msg the message sent. Should already be protocol-formatted.
*/
@ -114,20 +115,20 @@ public class Client {
} catch (IOException e) {
//e.printStackTrace();
LOGGER.debug("unable to send msg: " + msg);
disconnectFromServer();
}
}
/**
* parses a received message according to the client protocol.
*
* @param msg the message to be parsed.
*/
public void parse(String msg) {
JClientProtocolParser.parse(msg, this);
}
public void closeEverything() {
public void disconnectFromServer() {
try {
if (in != null) {
in.close();

View File

@ -1,7 +1,6 @@
package ch.unibas.dmi.dbis.cs108.multiplayer.client;
import ch.unibas.dmi.dbis.cs108.BudaLogConfig;
import ch.unibas.dmi.dbis.cs108.multiplayer.server.ClientHandler;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@ -41,7 +40,7 @@ public class JClientProtocolParser {
System.out.println(msg.substring(6));
break;
case "QUITC":
c.closeEverything();
c.disconnectFromServer();
break;
default:
System.out.println("Received unknown command");

View File

@ -3,6 +3,7 @@ package ch.unibas.dmi.dbis.cs108.multiplayer.server;
import ch.unibas.dmi.dbis.cs108.BudaLogConfig;
import ch.unibas.dmi.dbis.cs108.multiplayer.helpers.ServerPinger;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.util.HashSet;
import java.util.Scanner;
@ -17,20 +18,23 @@ public class ClientHandler implements Runnable {
private BufferedWriter out;
private BufferedReader in;
private Socket socket;
private InetAddress ip;
private
Scanner sc;
public ServerPinger serverPinger;
public static HashSet<ClientHandler> connectedClients = new HashSet<>();
public static HashSet<ClientHandler> disconnectedClients = new HashSet<>(); //todo: implement re-connection
public static HashSet<ClientHandler> lobby = new HashSet<>();
public static HashSet<ClientHandler> ghostClients = new HashSet<>();
/**
* Implements the login logic in client-server architecture.
*
* @param ip the ip of the client, used for re-connection.
* @param socket the socket on which to make the connection.
*/
public ClientHandler(Socket socket) {
public ClientHandler(Socket socket, InetAddress ip) {
try {
this.ip = ip;
this.socket = socket;
this.out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
this.in = new BufferedReader(new InputStreamReader((socket.getInputStream())));
@ -87,6 +91,7 @@ public class ClientHandler implements Runnable {
} catch (IOException e) {
//e.printStackTrace();
LOGGER.debug("Exception while trying to read message");
removeClientOnConnectionLoss();
break;
}
}
@ -146,9 +151,10 @@ public class ClientHandler implements Runnable {
}
}
/** Sends a given message to client
/** Sends a given message to client. The message has to already be protocol-formatted. ALL
* communication with the client has to happen via this method!
* todo: check for exception if out is closed.
* @param msg the given message
* @param msg the given message. Should already be protocol-formatted.
*/
public void sendMsgToClient(String msg) {
try {
@ -159,17 +165,39 @@ public class ClientHandler implements Runnable {
} catch (IOException e) {
//e.printStackTrace();
LOGGER.debug("unable to send msg: " + msg);
removeClientOnConnectionLoss();
}
}
/**
* Does exactly what it says on the tin, closes all connections of Client to Server.
* Removes & disconnects the client. To be used if a severe connection loss is detected (i.e. if trying to
* send / receive a message throws an exception, not just if ping-pong detects a connection loss).
* This is very similar to removeClientOnLogout(), however removeClientOnLogout() should only be used for
* regular quitting, since removeClientOnLogout() cannot handle a client with connection loss.
*/
public void disconnectClient() {
public void removeClientOnConnectionLoss() {
connectedClients.remove(this);
disconnectClient();
broadcastAnnouncement(getClientUserName() + " has left the server due to a connection loss.");
disconnectedClients.add(this);
}
/**
* Does exactly what it says on the tin, closes all connections of Client to Server and removes
* the client. To be used if the client requests logout or in other "regular" situations. Use
* removeClientOnConnectionLoss() if the client has to be removed due to a connection loss.
*/
public void removeClientOnLogout() {
broadcastAnnouncement(getClientUserName() + " has left the server.");
sendMsgToClient("QUITC");
connectedClients.remove(this);
disconnectClient();
}
/**
* Closes the client's socket, in, and out.
*/
public void disconnectClient() {
socket = this.getSocket();
in = this.getIn();
out = this.getOut();

View File

@ -56,7 +56,7 @@ public class JServerProtocolParser {
break;
case "QUITS":
//safely disconnects the user
h.disconnectClient();
h.removeClientOnLogout();
break;
default:
System.out.println("Received unknown command");

View File

@ -27,10 +27,10 @@ public class Server {
*/
public void startServer() {
try {
System.out.println("Port 42069 is open on " + this.serverSocket.getInetAddress()); //TODO: this is always 0.0.0.0
System.out.println("Port 42069 is open.");
while (!serverSocket.isClosed()) {
Socket socket = serverSocket.accept();
ClientHandler nextClient = new ClientHandler(socket);
ClientHandler nextClient = new ClientHandler(socket, socket.getInetAddress());
Thread th = new Thread(nextClient);
connectedClients.add(nextClient);
th.start();