Basics of client server communication and drawing of gamestates finished

This commit is contained in:
2021-02-18 11:42:11 +01:00
parent 8ed0e5196b
commit b7113b7ee8
15 changed files with 238 additions and 47 deletions

22
.idea/artifacts/Client.xml generated Normal file
View File

@@ -0,0 +1,22 @@
<component name="ArtifactManager">
<artifact type="javafx" name="Client">
<output-path>$PROJECT_DIR$/out/artifacts/Client</output-path>
<properties id="javafx-properties">
<options>
<option name="appClass" value="game.TicTacToe_Client" />
<option name="description" value="" />
<option name="height" value="" />
<option name="htmlPlaceholderId" value="" />
<option name="title" value="" />
<option name="vendor" value="" />
<option name="version" value="" />
<option name="width" value="" />
</options>
</properties>
<root id="root">
<element id="archive" name="Client.jar">
<element id="module-output" name="Client" />
</element>
</root>
</artifact>
</component>

View File

@@ -1,8 +0,0 @@
<component name="ArtifactManager">
<artifact type="jar" name="Client:jar">
<output-path>$PROJECT_DIR$/out/artifacts/Client_jar</output-path>
<root id="archive" name="Client.jar">
<element id="module-output" name="Client" />
</root>
</artifact>
</component>

View File

@@ -1,3 +1,3 @@
Manifest-Version: 1.0 Manifest-Version: 1.0
Main-Class: networking.Client Main-Class: game.TicTacToe_Client

View File

@@ -1,4 +1,4 @@
package games.TicTacToe; package game;
import javafx.application.Application; import javafx.application.Application;
import javafx.event.EventHandler; import javafx.event.EventHandler;
@@ -26,8 +26,6 @@ public class TicTacToe_Client extends Application {
grid.setGridLinesVisible(true); grid.setGridLinesVisible(true);
} }
private void drawCross(int column, int row){ private void drawCross(int column, int row){
Text cross = new Text("X"); Text cross = new Text("X");
cross.setFont(Font.font("Tahoma", FontWeight.NORMAL, 200)); cross.setFont(Font.font("Tahoma", FontWeight.NORMAL, 200));
@@ -40,7 +38,6 @@ public class TicTacToe_Client extends Application {
grid.add(circle, column, row); grid.add(circle, column, row);
} }
private void drawEmptyField(int column, int row) { private void drawEmptyField(int column, int row) {
Text emptyField = new Text(" "); Text emptyField = new Text(" ");
emptyField.setFont(Font.font("Tahoma", FontWeight.NORMAL, 200)); emptyField.setFont(Font.font("Tahoma", FontWeight.NORMAL, 200));
@@ -53,8 +50,8 @@ public class TicTacToe_Client extends Application {
return; return;
} }
for (int i = 0; i < gameState.length(); i++){ for (int i = 0; i < gameState.length(); i++){
int column = i % 3; int column = i / 3;
int row = i / 3; int row = i % 3;
if (gameState.charAt(i) == 'x'){ if (gameState.charAt(i) == 'x'){
this.drawCross(column, row); this.drawCross(column, row);
} else if (gameState.charAt(i) == 'o'){ } else if (gameState.charAt(i) == 'o'){
@@ -73,8 +70,16 @@ public class TicTacToe_Client extends Application {
scene.setOnMousePressed(new EventHandler<MouseEvent>() { scene.setOnMousePressed(new EventHandler<MouseEvent>() {
@Override @Override
public void handle(MouseEvent event) { public void handle(MouseEvent event) {
client.sendToServer(String.format("(%f|%f)", event.getX(), event.getY())); client.sendToServer("update");
client.getGameState(); client.sendToServer(String.format("%f|%f", event.getX(), event.getY()));
String gameState = client.getResponse();
if (gameState.length() == 9) {
drawBoard(gameState);
} else {
int column = (int) event.getX() / 300;
int row = (int) event.getY() / 300;
System.err.printf("You are not allowed to place at %f|%f%n", column, row);
}
} }
}); });
return scene; return scene;
@@ -82,6 +87,9 @@ public class TicTacToe_Client extends Application {
@Override @Override
public void start(Stage primaryStage) { public void start(Stage primaryStage) {
client = new Client("localhost", 2589, "TestClient");
client.handshake();
primaryStage.setTitle("TicTacToe"); primaryStage.setTitle("TicTacToe");
primaryStage.setResizable(false); primaryStage.setResizable(false);
@@ -91,10 +99,7 @@ public class TicTacToe_Client extends Application {
primaryStage.show(); primaryStage.show();
this.drawBoard("---------"); this.drawBoard(client.getGameState());
client = new Client("localhost", 2589, "TestClient");
client.handshake();
} }
public static void main(String[] args) { public static void main(String[] args) {

View File

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@@ -2,6 +2,8 @@ package networking;
import logging.ClientLogger; import logging.ClientLogger;
import logging.LogType; import logging.LogType;
import javax.swing.*;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
@@ -37,8 +39,9 @@ public class Client {
out.writeInt(165313125); out.writeInt(165313125);
out.flush(); out.flush();
success = in.readInt() == 200; success = in.readInt() == 200;
if (success){ if (success) {
out.writeUTF(name); out.writeUTF(name);
out.flush();
serverName = in.readUTF(); serverName = in.readUTF();
clientLogger.printLog("You successfully connected to me", serverName, success, LogType.Log); clientLogger.printLog("You successfully connected to me", serverName, success, LogType.Log);
} else { } else {
@@ -55,18 +58,37 @@ public class Client {
out.writeUTF(message); out.writeUTF(message);
out.flush(); out.flush();
success = in.readInt() == 200; success = in.readInt() == 200;
clientLogger.printLog(String.format("Sent the message: %s", message), serverName, success, LogType.Log);
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
public String getGameState(){ public String getResponse() {
try { try {
out.writeUTF("gamestate"); String message = in.readUTF();
return in.readUTF(); clientLogger.printLog(String.format("Message recieved: %s", message), serverName, success, LogType.Log);
return message;
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
public String getGameState() {
this.sendToServer("gameState");
String gameState = this.getResponse();
return gameState;
}
public void exitProcess(){
try {
out.writeUTF("exit()");
out.flush();
success = in.readInt()==200;
clientLogger.printLog("Closing connection to server", serverName, success, LogType.Log);
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
return "";
} }
} }
@@ -74,6 +96,8 @@ public class Client {
return success; return success;
} }
public String getName(){return name;} public String getName() {
return name;
}
} }

View File

@@ -0,0 +1,3 @@
Manifest-Version: 1.0
Main-Class: networking.Server

View File

@@ -0,0 +1,41 @@
package game;
import java.nio.charset.StandardCharsets;
public class TicTacToe_Server {
private String gameState;
public TicTacToe_Server(){
gameState = "---------";
}
public void setGameState(String gameState) {
this.gameState = gameState;
}
public String getGameState() {
return gameState;
}
public int makeClientMove(String input) {
int column = Double.valueOf(input.split("\\|")[0]).intValue() / 300;
int row = Double.valueOf(input.split("\\|")[1]).intValue() / 300;
int index = column * 3 + row;
if (isLegalMove(column, row)) {
byte[] gameStateBytes = gameState.getBytes();
gameStateBytes[index] = (byte) 'x';
gameState = new String(gameStateBytes, StandardCharsets.UTF_8);
return 200;
} else {
return 404;
}
}
private boolean isLegalMove(int column, int row){
int index = column * 3 + row;
return gameState.charAt(index) == '-';
}
}

View File

@@ -1,5 +1,6 @@
package networking; package networking;
import game.TicTacToe_Server;
import logging.LogType; import logging.LogType;
import logging.ServerLogger; import logging.ServerLogger;
@@ -15,7 +16,8 @@ public class Server {
private HashMap<Socket, String> clientNames; private HashMap<Socket, String> clientNames;
private HashMap<Socket, DataOutputStream> outstreams; private HashMap<Socket, DataOutputStream> outstreams;
private HashMap<Socket, DataInputStream> instreams; private HashMap<Socket, DataInputStream> instreams;
private ServerLogger logger; private TicTacToe_Server ticTacToe_server;
private ServerLogger serverLogger;
private Scanner scanner; private Scanner scanner;
private int requiredConnections; private int requiredConnections;
@@ -26,11 +28,12 @@ public class Server {
clientNames = new HashMap<>(); clientNames = new HashMap<>();
outstreams = new HashMap<>(); outstreams = new HashMap<>();
instreams = new HashMap<>(); instreams = new HashMap<>();
ticTacToe_server = new TicTacToe_Server();
scanner = new Scanner(System.in); scanner = new Scanner(System.in);
logger = new ServerLogger(); serverLogger = new ServerLogger();
requiredConnections = 1; requiredConnections = 1;
logger.printLog("Server started successfully", LogType.Log); serverLogger.printLog("Server started successfully", LogType.Log);
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
@@ -39,7 +42,7 @@ public class Server {
public void connectClients(){ public void connectClients(){
try { try {
int id = 0; int id = 0;
logger.printLog(String.format("Waiting for %d clients to connect ...", requiredConnections), LogType.Log); serverLogger.printLog(String.format("Waiting for %d clients to connect ...", requiredConnections), LogType.Log);
while(clients.size() < requiredConnections) { while(clients.size() < requiredConnections) {
Socket momentaryClient = serverSocket.accept(); Socket momentaryClient = serverSocket.accept();
clients.put(id, momentaryClient); clients.put(id, momentaryClient);
@@ -62,7 +65,7 @@ public class Server {
clientNames.put(client, instreams.get(client).readUTF()); clientNames.put(client, instreams.get(client).readUTF());
outstreams.get(client).writeUTF(serverSocket.getInetAddress().getHostAddress()+":"+serverSocket.getLocalPort()); outstreams.get(client).writeUTF(serverSocket.getInetAddress().getHostAddress()+":"+serverSocket.getLocalPort());
outstreams.get(client).flush(); outstreams.get(client).flush();
logger.printLog(String.format("%s got connected", clientNames.get(client)), LogType.Log); serverLogger.printLog(String.format("%s got connected", clientNames.get(client)), LogType.Log);
} else { } else {
outstreams.get(client).writeInt(403); outstreams.get(client).writeInt(403);
outstreams.get(client).flush(); outstreams.get(client).flush();
@@ -74,19 +77,16 @@ public class Server {
} }
} }
public void getMessages(){ public void ticTacToe_gameloop(){
for (Socket client: clients.values()) { for (Socket client: clients.values()) {
try { try {
while (true) { while (!client.isClosed()) {
String message = instreams.get(client).readUTF(); String message = instreams.get(client).readUTF();
if (!message.equalsIgnoreCase("exit()")) { serverLogger.printLog(message, clientNames.get(client), LogType.Message);
logger.printLog(message, clientNames.get(client), LogType.Message);
} else {
outstreams.get(client).writeInt(200);
logger.printLog(String.format("%s closed the connection",clientNames.get(client)), LogType.Log);
break;
}
outstreams.get(client).writeInt(200); outstreams.get(client).writeInt(200);
outstreams.get(client).flush();
serverLogger.printLog("Sent verification code", clientNames.get(client), LogType.Log);
this.gameFlow(message, client);
} }
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
@@ -97,10 +97,56 @@ public class Server {
} }
} }
} }
clients.clear(); }
System.out.println("Do you want to keep the server alive and wait for other clients ? [y]/[n]");
if (scanner.nextLine().equalsIgnoreCase("y")){ public void gameFlow(String input, Socket client){
this.connectClients(); switch (input){
case "gameState":
try {
outstreams.get(client).writeUTF(ticTacToe_server.getGameState());
outstreams.get(client).flush();
serverLogger.printLog("Sent gameState", clientNames.get(client), LogType.Log);
break;
} catch (IOException e) {
e.printStackTrace();
}
case "update":
try {
String position = instreams.get(client).readUTF();
serverLogger.printLog(position, clientNames.get(client), LogType.Message);
outstreams.get(client).writeInt(200);
outstreams.get(client).flush();
serverLogger.printLog("Sent verification code", clientNames.get(client), LogType.Log);
int verificationCode = ticTacToe_server.makeClientMove(position);
if (verificationCode == 200) {
String gameState = ticTacToe_server.getGameState();
outstreams.get(client).writeUTF(gameState);
outstreams.get(client).flush();
serverLogger.printLog(String.format("Sent gameState: %s", gameState), clientNames.get(client), LogType.Log);
break;
} else {
outstreams.get(client).writeUTF(" ");
outstreams.get(client).flush();
serverLogger.printLog(String.format("Move is not allowed!"), clientNames.get(client), LogType.Error);
break;
}
} catch (IOException e) {
e.printStackTrace();
}
case "exit()":
try {
outstreams.get(client).writeInt(200);
outstreams.get(client).flush();
outstreams.get(client).close();
instreams.get(client).close();
client.close();
serverLogger.printLog(String.format("%s closed the connection",clientNames.get(client)), LogType.Log);
break;
} catch (IOException e) {
e.printStackTrace();
}
} }
} }
@@ -108,6 +154,6 @@ public class Server {
Server server = new Server(2589); Server server = new Server(2589);
server.connectClients(); server.connectClients();
server.handshake(); server.handshake();
server.getMessages(); server.ticTacToe_gameloop();
} }
} }

View File

@@ -0,0 +1,43 @@
<html><head>
<SCRIPT src="http://java.com/js/dtjava.js"></SCRIPT>
<script>
function launchApplication(jnlpfile) {
dtjava.launch( {
url : 'Client.jnlp'
},
{
javafx : '8.0+'
},
{}
);
return false;
}
</script>
<script>
function javafxEmbedClient_id() {
dtjava.embed(
{
id : 'Client_id',
url : 'Client.jnlp',
placeholder : 'javafx-app-placeholder',
width : '900',
height : '900'
},
{
javafx : '8.0+'
},
{}
);
}
<!-- Embed FX application into web page once page is loaded -->
dtjava.addOnloadCallback(javafxEmbedClient_id);
</script>
</head><body>
<h2>Test page for <b>Client</b></h2>
<b>Webstart:</b> <a href='Client.jnlp' onclick="return launchApplication('Client.jnlp');">click to launch this app as webstart</a><br><hr><br>
<!-- Applet will be inserted here -->
<div id='javafx-app-placeholder'></div>
</body></html>

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<jnlp spec="1.0" xmlns:jfx="http://javafx.com" href="Client.jnlp">
<information>
<title>Client</title>
<vendor>Unknown</vendor>
<description>Client</description>
<offline-allowed/>
</information>
<resources>
<j2se version="1.6+" href="http://java.sun.com/products/autodl/j2se"/>
<jar href="Client.jar" size="9642" download="eager" />
</resources>
<jfx:javafx-desc width="900" height="900" main-class="game.TicTacToe_Client" name="Client" />
<update check="background"/>
</jnlp>

View File

@@ -1,3 +1,3 @@
Manifest-Version: 1.0 Manifest-Version: 1.0
Main-Class: networking.Client Main-Class: game.TicTacToe_Client

View File

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB