complete overhaul of client / server communication. Several methods renamed, tweaked protocol.
This commit is contained in:
parent
52a6a0cd65
commit
f677f5cb71
@ -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.
|
||||
}
|
||||
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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");
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -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");
|
||||
|
||||
Reference in New Issue
Block a user