mirror of
https://github.com/michaelrausch/Party-Parrots-At-Sea.git
synced 2026-05-09 06:18:44 +00:00
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:
@@ -3,14 +3,10 @@ package seng302.gameServer;
|
|||||||
import seng302.models.Player;
|
import seng302.models.Player;
|
||||||
import seng302.models.Yacht;
|
import seng302.models.Yacht;
|
||||||
import seng302.server.messages.*;
|
import seng302.server.messages.*;
|
||||||
import seng302.server.simulator.Boat;
|
|
||||||
import seng302.server.simulator.Simulator;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.SocketOption;
|
|
||||||
import java.net.SocketOptions;
|
|
||||||
import java.nio.channels.ServerSocketChannel;
|
import java.nio.channels.ServerSocketChannel;
|
||||||
import java.nio.channels.SocketChannel;
|
import java.nio.channels.SocketChannel;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@@ -280,7 +276,7 @@ public class GameServerThread implements Runnable, Observer, ClientConnectionDel
|
|||||||
|
|
||||||
startTime = System.currentTimeMillis() + TIME_TILL_RACE_START;
|
startTime = System.currentTimeMillis() + TIME_TILL_RACE_START;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// /**
|
// /**
|
||||||
@@ -360,41 +356,42 @@ public class GameServerThread implements Runnable, Observer, ClientConnectionDel
|
|||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void update(Observable o, Object arg) {
|
public void update(Observable o, Object arg) {
|
||||||
/* Only send if server started
|
// /* 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
|
//// // 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()){
|
// if (server == null || !server.isStarted()) {
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
int numOfBoatsFinished = 0;
|
// int numOfBoatsFinished = 0;
|
||||||
for (Boat boat : (List<Boat>) arg){
|
// for (Boat boat : (List<Boat>) arg) {
|
||||||
try {
|
// try {
|
||||||
if (boat.isFinished()) {
|
// if (boat.isFinished()) {
|
||||||
numOfBoatsFinished ++;
|
// numOfBoatsFinished++;
|
||||||
if (!boatsFinished.get(boat.getSourceID())) {
|
// if (!boatsFinished.get(boat.getSourceID())) {
|
||||||
boatsFinished.put(boat.getSourceID(), true);
|
// boatsFinished.put(boat.getSourceID(), true);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
Message m = new BoatLocationMessage(boat.getSourceID(), 1, boat.getLat(),
|
// Message m = new BoatLocationMessage(boat.getSourceID(), 1, boat.getLat(),
|
||||||
boat.getLng(), boat.getLastPassedCorner().getBearingToNextCorner(),
|
// boat.getLng(), boat.getLastPassedCorner().getBearingToNextCorner(),
|
||||||
((long) boat.getSpeed()));
|
// ((long) boat.getSpeed()));
|
||||||
broadcast(m);
|
// broadcast(m);
|
||||||
} catch (IOException e) {
|
// } catch (IOException e) {
|
||||||
serverLog("Couldn't send a boat status message", 3);
|
// serverLog("Couldn't send a boat status message", 3);
|
||||||
return;
|
// return;
|
||||||
}
|
// } catch (NullPointerException e) {
|
||||||
catch (NullPointerException e){
|
// e.printStackTrace();
|
||||||
e.printStackTrace();
|
// }
|
||||||
}*/
|
// }
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// if (numOfBoatsFinished == ((List<Boat>) arg).size()) {
|
// if (numOfBoatsFinished == ((List<Boat>) arg).size()) {
|
||||||
// startSendingRaceFinishedBoatPositions();
|
// startSendingRaceFinishedBoatPositions();
|
||||||
// }
|
// }
|
||||||
|
|
||||||
//}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void terminateGame() {
|
public void terminateGame() {
|
||||||
try {
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user