Call me Joni Mitchell because quit due to connection loss works on both sides now.
This commit is contained in:
parent
de69ea27bb
commit
faa2b61acb
@ -6,7 +6,6 @@ import ch.unibas.dmi.dbis.cs108.multiplayer.helpers.ClientPinger;
|
|||||||
|
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.net.SocketException;
|
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Scanner;
|
import java.util.Scanner;
|
||||||
@ -88,11 +87,12 @@ public class Client {
|
|||||||
try {
|
try {
|
||||||
chatMsg = in.readLine(); //todo: maybe if
|
chatMsg = in.readLine(); //todo: maybe if
|
||||||
if (chatMsg != null) {
|
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) {
|
} catch (IOException e) {
|
||||||
//e.printStackTrace();
|
//e.printStackTrace();
|
||||||
LOGGER.debug("Exception while trying to read message");
|
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.
|
* @param msg the message sent. Should already be protocol-formatted.
|
||||||
*/
|
*/
|
||||||
@ -114,20 +115,20 @@ public class Client {
|
|||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
//e.printStackTrace();
|
//e.printStackTrace();
|
||||||
LOGGER.debug("unable to send msg: " + msg);
|
LOGGER.debug("unable to send msg: " + msg);
|
||||||
|
disconnectFromServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* parses a received message according to the client protocol.
|
* parses a received message according to the client protocol.
|
||||||
*
|
|
||||||
* @param msg the message to be parsed.
|
* @param msg the message to be parsed.
|
||||||
*/
|
*/
|
||||||
public void parse(String msg) {
|
public void parse(String msg) {
|
||||||
JClientProtocolParser.parse(msg, this);
|
JClientProtocolParser.parse(msg, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void closeEverything() {
|
public void disconnectFromServer() {
|
||||||
try {
|
try {
|
||||||
if (in != null) {
|
if (in != null) {
|
||||||
in.close();
|
in.close();
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
package ch.unibas.dmi.dbis.cs108.multiplayer.client;
|
package ch.unibas.dmi.dbis.cs108.multiplayer.client;
|
||||||
|
|
||||||
import ch.unibas.dmi.dbis.cs108.BudaLogConfig;
|
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.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
@ -41,7 +40,7 @@ public class JClientProtocolParser {
|
|||||||
System.out.println(msg.substring(6));
|
System.out.println(msg.substring(6));
|
||||||
break;
|
break;
|
||||||
case "QUITC":
|
case "QUITC":
|
||||||
c.closeEverything();
|
c.disconnectFromServer();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
System.out.println("Received unknown command");
|
System.out.println("Received unknown command");
|
||||||
|
|||||||
@ -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.BudaLogConfig;
|
||||||
import ch.unibas.dmi.dbis.cs108.multiplayer.helpers.ServerPinger;
|
import ch.unibas.dmi.dbis.cs108.multiplayer.helpers.ServerPinger;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
import java.net.InetAddress;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Scanner;
|
import java.util.Scanner;
|
||||||
@ -17,20 +18,23 @@ public class ClientHandler implements Runnable {
|
|||||||
private BufferedWriter out;
|
private BufferedWriter out;
|
||||||
private BufferedReader in;
|
private BufferedReader in;
|
||||||
private Socket socket;
|
private Socket socket;
|
||||||
|
private InetAddress ip;
|
||||||
private
|
private
|
||||||
Scanner sc;
|
Scanner sc;
|
||||||
public ServerPinger serverPinger;
|
public ServerPinger serverPinger;
|
||||||
public static HashSet<ClientHandler> connectedClients = new HashSet<>();
|
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> lobby = new HashSet<>();
|
||||||
public static HashSet<ClientHandler> ghostClients = new HashSet<>();
|
public static HashSet<ClientHandler> ghostClients = new HashSet<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements the login logic in client-server architecture.
|
* 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.
|
* @param socket the socket on which to make the connection.
|
||||||
*/
|
*/
|
||||||
public ClientHandler(Socket socket) {
|
public ClientHandler(Socket socket, InetAddress ip) {
|
||||||
try {
|
try {
|
||||||
|
this.ip = ip;
|
||||||
this.socket = socket;
|
this.socket = socket;
|
||||||
this.out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
|
this.out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
|
||||||
this.in = new BufferedReader(new InputStreamReader((socket.getInputStream())));
|
this.in = new BufferedReader(new InputStreamReader((socket.getInputStream())));
|
||||||
@ -87,6 +91,7 @@ public class ClientHandler implements Runnable {
|
|||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
//e.printStackTrace();
|
//e.printStackTrace();
|
||||||
LOGGER.debug("Exception while trying to read message");
|
LOGGER.debug("Exception while trying to read message");
|
||||||
|
removeClientOnConnectionLoss();
|
||||||
break;
|
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.
|
* 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) {
|
public void sendMsgToClient(String msg) {
|
||||||
try {
|
try {
|
||||||
@ -159,17 +165,39 @@ public class ClientHandler implements Runnable {
|
|||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
//e.printStackTrace();
|
//e.printStackTrace();
|
||||||
LOGGER.debug("unable to send msg: " + msg);
|
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.");
|
broadcastAnnouncement(getClientUserName() + " has left the server.");
|
||||||
sendMsgToClient("QUITC");
|
sendMsgToClient("QUITC");
|
||||||
connectedClients.remove(this);
|
connectedClients.remove(this);
|
||||||
|
disconnectClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes the client's socket, in, and out.
|
||||||
|
*/
|
||||||
|
public void disconnectClient() {
|
||||||
socket = this.getSocket();
|
socket = this.getSocket();
|
||||||
in = this.getIn();
|
in = this.getIn();
|
||||||
out = this.getOut();
|
out = this.getOut();
|
||||||
|
|||||||
@ -56,7 +56,7 @@ public class JServerProtocolParser {
|
|||||||
break;
|
break;
|
||||||
case "QUITS":
|
case "QUITS":
|
||||||
//safely disconnects the user
|
//safely disconnects the user
|
||||||
h.disconnectClient();
|
h.removeClientOnLogout();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
System.out.println("Received unknown command");
|
System.out.println("Received unknown command");
|
||||||
|
|||||||
@ -27,10 +27,10 @@ public class Server {
|
|||||||
*/
|
*/
|
||||||
public void startServer() {
|
public void startServer() {
|
||||||
try {
|
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()) {
|
while (!serverSocket.isClosed()) {
|
||||||
Socket socket = serverSocket.accept();
|
Socket socket = serverSocket.accept();
|
||||||
ClientHandler nextClient = new ClientHandler(socket);
|
ClientHandler nextClient = new ClientHandler(socket, socket.getInetAddress());
|
||||||
Thread th = new Thread(nextClient);
|
Thread th = new Thread(nextClient);
|
||||||
connectedClients.add(nextClient);
|
connectedClients.add(nextClient);
|
||||||
th.start();
|
th.start();
|
||||||
|
|||||||
Reference in New Issue
Block a user