WIP: Worked on new server thread class that would create and store multiple THREADS of connections. Researched Authorative server structures

tags: #story[1047]
This commit is contained in:
William Muir
2017-07-13 22:55:03 +12:00
parent 1e6fd1af09
commit c480fca72a
3 changed files with 204 additions and 35 deletions
@@ -3,14 +3,10 @@ package seng302.gameServer;
import seng302.models.Player;
import seng302.models.Yacht;
import seng302.server.messages.*;
import seng302.server.simulator.Boat;
import seng302.server.simulator.Simulator;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.net.SocketOption;
import java.net.SocketOptions;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.*;
@@ -360,41 +356,42 @@ public class GameServerThread implements Runnable, Observer, ClientConnectionDel
@Override
@SuppressWarnings("unchecked")
public void update(Observable o, Object arg) {
/* Only send if server started
// TODO: I don't understand why i need to check server is null or not ... confused - haoming 2/5/17
if(server == null || !server.isStarted()){
return;
}
int numOfBoatsFinished = 0;
for (Boat boat : (List<Boat>) arg){
try {
if (boat.isFinished()) {
numOfBoatsFinished ++;
if (!boatsFinished.get(boat.getSourceID())) {
boatsFinished.put(boat.getSourceID(), true);
}
}
Message m = new BoatLocationMessage(boat.getSourceID(), 1, boat.getLat(),
boat.getLng(), boat.getLastPassedCorner().getBearingToNextCorner(),
((long) boat.getSpeed()));
broadcast(m);
} catch (IOException e) {
serverLog("Couldn't send a boat status message", 3);
return;
}
catch (NullPointerException e){
e.printStackTrace();
}*/
}
// /* Only send if server started*/
//// // TODO: I don't understand why i need to check server is null or not ... confused - haoming 2/5/17
// if (server == null || !server.isStarted()) {
// return;
// }
//
// int numOfBoatsFinished = 0;
// for (Boat boat : (List<Boat>) arg) {
// try {
// if (boat.isFinished()) {
// numOfBoatsFinished++;
// if (!boatsFinished.get(boat.getSourceID())) {
// boatsFinished.put(boat.getSourceID(), true);
// }
// }
// Message m = new BoatLocationMessage(boat.getSourceID(), 1, boat.getLat(),
// boat.getLng(), boat.getLastPassedCorner().getBearingToNextCorner(),
// ((long) boat.getSpeed()));
// broadcast(m);
// } catch (IOException e) {
// serverLog("Couldn't send a boat status message", 3);
// return;
// } catch (NullPointerException e) {
// e.printStackTrace();
// }
// }
// if (numOfBoatsFinished == ((List<Boat>) arg).size()) {
// startSendingRaceFinishedBoatPositions();
// }
//}
}
public void terminateGame() {
try {
@@ -0,0 +1,105 @@
package seng302.gameServerWithThreading;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
/**
* A class describing a single connection to a Client for the purposes of sending and receiving on its own thread.
* All server threads created and owned by the server thread handler which can trigger client updates on its threads
* Created by wmu16 on 13/07/17.
*/
public class ServerThread extends Thread {
private static final Integer MAX_ID_ATTEMPTS = 10;
private InputStream is;
private OutputStream os;
private Socket socket;
private Boolean userIdentified = false;
private Boolean connected = true;
private Boolean updateClient = true;
public ServerThread(Socket socket) {
this.socket = socket;
}
public void run() {
try {
is = socket.getInputStream();
os = socket.getOutputStream();
} catch (IOException e) {
System.out.println("IO error in server thread upon grabbing streams");
}
threeWayHandshake();
// TODO: 13/07/17 wmu16 - Some way of knowing if the client is still connected. perhaps when we read disconnect message switch this bool?
while (connected) {
//Perform a read and update game state
try {
Integer userInput = is.read();
} catch (IOException e) {
System.out.println("IO error in server thread upon reading input stream");
}
//Perform a write if it is time to as delegated by the ServerThreadHandler
if (updateClient) {
// TODO: 13/07/17 wmu16 - Write out game state - some function that would write all appropriate messages to this output stream
// try {
// GameState.outputState(os);
// } catch (IOException e) {
// System.out.println("IO error in server thread upon writing to output stream");
// }
updateClient = false;
}
}
closeSocket();
}
public void updateClient() {
updateClient = true;
}
/**
* Tries to confirm the connection just accepted.
* Sends ID, expects that ID echoed for confirmation,
* if so, sends a confirmation packet back to that connection
* Creates a player instance with that ID and this thread and adds it to the GameState
* If not, close the socket and end the threads execution
*/
private void threeWayHandshake() {
// TODO: 13/07/17 Finish using AC35
// Integer playerID = GameState.getUniquePlayerID();
// Integer confirmationID = null;
// Integer identificationAttempt = 0
// while (!userIdentified) {
// os.write(playerID); //Send out new ID looking for echo
// confirmationID = is.read();
// if (playerID == idConfirmation) { //ID is echoed back. Connection is a client
// os.write( some determined confirmation message ); //Confirm to client
// GameState.addPlayer(new Player(playerID, this)); //Create a player in game state for client
// userIdentified = true;
// } else if (identificationAttempt > MAX_ID_ATTEMPTS) { //No response. not a client. tidy up and go home.
// closeSocket();
// return;
// }
// identificationAttempt++;
// }
}
public void closeSocket() {
try {
socket.close();
} catch (IOException e) {
System.out.println("IO error in server thread upon trying to close socket");
}
}
}
@@ -0,0 +1,67 @@
package seng302.gameServerWithThreading;
import seng302.gameServer.GameStages;
import seng302.gameServer.GameState;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
/**
* A class describing the overall server, which creates and collects server threads for each client
* Created by wmu16 on 13/07/17.
*/
public class ServerThreadHandler extends Thread {
private static final int PORT = 4950;
private static final Integer MAX_NUM_PLAYERS = 10;
private ServerSocket serverSocket = null;
private Socket socket;
private ArrayList<ServerThread> serverThreads = new ArrayList<>();
public ServerThreadHandler() {
try {
serverSocket = new ServerSocket(PORT);
} catch (IOException e) {
System.out.println("IO error in server thread handler upon trying to make new server socket");
}
}
public void run() {
//You should handle interrupts in some way, so that the thread won't keep on forever if you exit the app.
while (!isInterrupted()) {
try {
Thread.sleep(1000 / 60); //60 times per second we should calculate the game state
} catch (InterruptedException e) {
e.printStackTrace();
}
if (GameState.getCurrentStage() == GameStages.LOBBYING && GameState.getPlayers().size() < MAX_NUM_PLAYERS) {
try {
socket = serverSocket.accept();
} catch (IOException e) {
System.out.println("IO error in server thread handler upon trying to accept connection");
}
ServerThread thread = new ServerThread(socket);
serverThreads.add(thread);
thread.start();
}
updateClients();
}
try {
serverSocket.close();
} catch (IOException e) {
System.out.println("IO error in server thread handler upon closing socket");
}
}
public void updateClients() {
for (ServerThread serverThread : serverThreads) {
serverThread.updateClient();
}
}
}