complete overhaul of client / server communication. Several methods renamed, tweaked protocol.

This commit is contained in:
Jonas 2022-04-02 17:10:29 +02:00
parent 52a6a0cd65
commit f677f5cb71
9 changed files with 70 additions and 59 deletions

View File

@ -16,7 +16,7 @@ public class BudaLogConfig {
LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
Configuration config = ctx.getConfiguration();
LoggerConfig loggerConfig = config.getLoggerConfig(LogManager.ROOT_LOGGER_NAME);
loggerConfig.setLevel(Level.TRACE); // change level here
loggerConfig.setLevel(Level.DEBUG); // change level here
ctx.updateLoggers(); // This causes all Loggers to refetch information from their LoggerConfig.
}

View File

@ -6,6 +6,7 @@ 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.Scanner;
import org.apache.logging.log4j.LogManager;
@ -27,14 +28,9 @@ public class Client {
this.socket = socket;
this.out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
this.in = new BufferedReader((new InputStreamReader((socket.getInputStream()))));
//TODO add the system based generated username here.
//TODO hide connecting logik(next 4 lines)
this.userName = userName;
this.out.write(getUsername());
this.out.newLine();
this.out.flush();
clientPinger = new ClientPinger(this.out, this.socket);
sendMsgToServer(getUsername());
clientPinger = new ClientPinger(this, this.socket);
} catch (IOException e) {
e.printStackTrace();
closeEverything(socket, in, out);
@ -44,20 +40,19 @@ public class Client {
/**
* Sends a message to the Server in a formatted way COMND$msg
*/
public void sendMessage() {
try {
public void userInputListener() {
new Thread(new Runnable() {
@Override
public void run() {
Scanner sc = new Scanner(System.in);
while (socket.isConnected()) {
while (socket.isConnected() && !socket.isClosed()) {
String msg = sc.nextLine();
String formattedMSG = MessageFormatter.formatMsg(msg);
out.write(formattedMSG);
out.newLine();
out.flush();
sendMsgToServer(formattedMSG);
}
} catch (IOException e) {
e.printStackTrace();
closeEverything(socket, in, out);
LOGGER.debug("userInputListener is done");
}
}).start();
}
@ -74,16 +69,19 @@ public class Client {
String chatMsg;
while (socket.isConnected()) {
while (socket.isConnected() && !socket.isClosed()) {
try {
chatMsg = in.readLine();
parse(chatMsg);
if (chatMsg != null) {
parse(chatMsg); //todo: i think this trows an error BC chatMsg is null if client disconnects
}
} catch (IOException e) {
e.printStackTrace();
closeEverything(socket, in, out);
}
}
LOGGER.debug("chatListener is done");
}
}).start();
}
@ -152,7 +150,7 @@ public class Client {
client.chatListener();
Thread cP = new Thread(client.clientPinger);
cP.start();
client.sendMessage(); //this one blocks.
client.userInputListener(); //this one blocks.
} catch (UnknownHostException e) {
System.out.println("Invalid host IP");
} catch (IOException e) {

View File

@ -38,6 +38,9 @@ public class JClientProtocolParser {
*/
System.out.println(msg.substring(6));
break;
case "QUITC":
//c.closeEverything(); todo: this line.
System.out.println("bye!");
default:
System.out.println("Received unknown command");
}

View File

@ -19,16 +19,20 @@ public class MessageFormatter {
public static String formatMsg(String msg) {
String header = ""; //header is first two characters
StringBuilder stringBuilder = new StringBuilder();
String s; // just a friendly helper to save message in
String s = ""; // just a friendly helper to save message in
try {
header = msg.substring(0, 2);
} catch (IndexOutOfBoundsException e) {
e.printStackTrace();
header = "";
}
switch (header) {
case "/c":
stringBuilder.append("CHATA$");
try {
s = msg.substring(3);
} catch (Exception e) {
System.out.println("You didn't even write a chat line, you silly billy!");
}
break;
case "/q":
stringBuilder.append("QUITS$");
@ -36,7 +40,11 @@ public class MessageFormatter {
break;
case "/n":
stringBuilder.append("NAMEC$");
try {
s = msg.substring(3);
} catch (Exception e) {
System.out.println("Well what do you want your name to be?");
}
break;
default:
s = msg;

View File

@ -1,6 +1,7 @@
package ch.unibas.dmi.dbis.cs108.multiplayer.helpers;
import ch.unibas.dmi.dbis.cs108.BudaLogConfig;
import ch.unibas.dmi.dbis.cs108.multiplayer.client.Client;
import java.io.BufferedWriter;
import java.io.IOException;
import java.net.Socket;
@ -18,19 +19,17 @@ public class ClientPinger implements Runnable {
private boolean gotPingBack; //should be set to true when client gets a pingback.
private boolean isConnected; //set to true unless the ClientPinger detects a connection loss.
BufferedWriter out; //the output of this client through which the pings are sent
private Socket socket;
private final Client client;
private final Socket socket;
/**
* @param socket the socket the Client is connected to which is used to end the thread if the
* connection is lost.
*
* @param out the output through which the pings are sent.
*/
public ClientPinger(BufferedWriter out, Socket socket) {
public ClientPinger(Client client, Socket socket) {
gotPingBack = false;
isConnected = true;
this.out = out;
this.client = client;
this.socket = socket;
}
@ -38,11 +37,9 @@ public class ClientPinger implements Runnable {
public void run() {
try {
Thread.sleep(2000);
while (socket.isConnected()) {
while (socket.isConnected() && !socket.isClosed()) {
gotPingBack = false;
out.write("CPING");
out.newLine();
out.flush();
client.sendMsgToServer("CPING");
Thread.sleep(4000);
if (gotPingBack) {
if (!isConnected) { //if !isConnected, then the connection had been lost before.
@ -56,8 +53,8 @@ public class ClientPinger implements Runnable {
}
}
}
isConnected = false; //in case the socket accidentally disconnects (can this happen?)
} catch (InterruptedException | IOException e) {
isConnected = false;
} catch (InterruptedException e) {
e.printStackTrace();
}
}

View File

@ -2,7 +2,10 @@ Client commands:
Implemented:
* CHATA$message Send chat message to all
* QUITS quit server/ leave server
* QUITS request to quit server/ leave server. The server should then remove the
relevant ClientHandler and close the sockets, but before doing so, it sends
"QUITC" to the client to confirm the quitting. The client doesn't close any
sockets until receiving "QUITC"
* CPING Ping from client to server.
* PINGB Pingback from client to server.
* NAMEC$name Change name to whatever is specified
@ -22,6 +25,7 @@ Server Commands:
Implemented:
* SPING Ping from server to client
* PINGB Pingback from client to server.
* QUITC Confirms to the client that they are being disconnected from the server.
Future / planned:
* MSGRS "Message received": Paramaters: a string detailing to the client that and what the server received as command.

View File

@ -38,9 +38,9 @@ public class ServerPinger implements Runnable {
public void run() {
try {
Thread.sleep(2000);
while (socket.isConnected()) {
while (socket.isConnected() && !socket.isClosed()) {
gotPingBack = false;
out.write("SPING");
out.write("SPING"); //todo: throws exception when client disconnects.
out.newLine();
out.flush();
Thread.sleep(4000);

View File

@ -17,6 +17,7 @@ public class ClientHandler implements Runnable {
private BufferedWriter out;
private BufferedReader in;
private Socket socket;
private
Scanner sc;
public ServerPinger serverPinger;
public static HashSet<ClientHandler> connectedClients = new HashSet<>();
@ -44,10 +45,9 @@ public class ClientHandler implements Runnable {
serverPinger = new ServerPinger(out, socket);
Thread sP = new Thread(serverPinger);
sP.start();
broadcastMessage("SERVER: " + clientUserName + " has joined the Server");
broadcastChatMessage("SERVER: " + clientUserName + " has joined the Server");
} catch (IOException e) {
e.printStackTrace();
closeEverything(socket, in, out);
}
}
@ -87,13 +87,12 @@ public class ClientHandler implements Runnable {
**/
public void run() {
String msg;
while (socket.isConnected()) {
while (socket.isConnected() && !socket.isClosed()) {
try {
msg = in.readLine(); //todo: here is where the server throws an exception when the client quits
JServerProtocolParser.parse(msg, this);
} catch (IOException e) {
e.printStackTrace();
closeEverything(socket, in, out);
break;
}
}
@ -116,7 +115,7 @@ public class ClientHandler implements Runnable {
String h = this.clientUserName; //just a friendly little helper
this.clientUserName = newName;
AllClientNames.allNames(newName);
broadcastMessage(h + " have changed their nickname to " + clientUserName);
broadcastChatMessage(h + " have changed their nickname to " + clientUserName);
}
/**
@ -124,10 +123,9 @@ public class ClientHandler implements Runnable {
*
* @param msg the Message to be broadcasted
*/
public void broadcastMessage(String msg) {
public void broadcastChatMessage(String msg) {
for (ClientHandler client : connectedClients) {
client.sendMsgToClient("CHATM:" + clientUserName + ": \"" + msg + "\"");
client.sendMsgToClient("CHATM$" + clientUserName + ": \"" + msg + "\"");
}
}
@ -135,9 +133,9 @@ public class ClientHandler implements Runnable {
* todo: check for exception if out is closed.
* @param msg the given message
*/
public void sendMsgToClient(String msg) {
try {
//todo: socket closed handling
out.write(msg);
out.newLine();
out.flush();
@ -150,8 +148,8 @@ public class ClientHandler implements Runnable {
* Does what it sounds like
*/
public void removeClientHandler() {
broadcastChatMessage("SERVER: " + clientUserName + " has left the server");
connectedClients.remove(this);
broadcastMessage("SERVER: " + clientUserName + " has left the server");
}
/**
@ -161,9 +159,14 @@ public class ClientHandler implements Runnable {
* @param in the in-Stream reader to be closed
* @param out the out-Stream Write to be closed
*/
public void closeEverything(Socket socket, BufferedReader in, BufferedWriter out) {
public void disconnectClient() {
sendMsgToClient("QUITC");
removeClientHandler();
socket = this.getSocket();
in = this.getIn();
out = this.getOut();
try {
Thread.sleep(100);
if (in != null) {
in.close();
}
@ -173,12 +176,10 @@ public class ClientHandler implements Runnable {
if (socket != null) {
socket.close();
}
} catch (IOException e) {
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
public void decodeMsg(String msg) {
}
}

View File

@ -30,7 +30,7 @@ public class JServerProtocolParser {
switch (header) {
case CHATA:
//sends chat message to all connected clients
h.broadcastMessage(msg.substring(6));
h.broadcastChatMessage(msg.substring(6));
break;
case "NAMEC":
//changes name to whatever follows NAMEC$. If the new name is already in use, it will append
@ -47,7 +47,7 @@ public class JServerProtocolParser {
break;
case "QUITS":
//safely disconnects the user
h.closeEverything(h.getSocket(), h.getIn(), h.getOut());
h.disconnectClient();
break;
default:
System.out.println("Received unknown command");