Some more improvements to socket handling.
This commit is contained in:
parent
9be9a15fa0
commit
dfc7ac6978
|
@ -1,17 +1,22 @@
|
||||||
package nl.andrewl.starship_arena.server;
|
package nl.andrewl.starship_arena.server;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
import nl.andrewl.starship_arena.server.model.Arena;
|
import nl.andrewl.starship_arena.server.model.Arena;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
public class ClientManager extends Thread {
|
public class ClientManager extends Thread {
|
||||||
private final Arena arena;
|
private final Arena arena;
|
||||||
private final Socket clientSocket;
|
private final Socket clientSocket;
|
||||||
|
@Getter
|
||||||
|
private final UUID clientId;
|
||||||
|
|
||||||
public ClientManager(Arena arena, Socket clientSocket) {
|
public ClientManager(Arena arena, Socket clientSocket, UUID id) {
|
||||||
this.arena = arena;
|
this.arena = arena;
|
||||||
this.clientSocket = clientSocket;
|
this.clientSocket = clientSocket;
|
||||||
|
this.clientId = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
|
@ -24,7 +29,7 @@ public class ClientManager extends Thread {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
while (clientSocket.isConnected() && !clientSocket.isClosed()) {
|
while (!clientSocket.isClosed()) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,12 +3,15 @@ package nl.andrewl.starship_arena.server;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import nl.andrewl.starship_arena.server.data.ArenaStore;
|
import nl.andrewl.starship_arena.server.data.ArenaStore;
|
||||||
|
import nl.andrewl.starship_arena.server.model.Arena;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||||
import org.springframework.context.event.EventListener;
|
import org.springframework.context.event.EventListener;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.PreDestroy;
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.DatagramSocket;
|
import java.net.DatagramSocket;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
@ -48,6 +51,17 @@ public class SocketGateway implements Runnable {
|
||||||
new Thread(this).start();
|
new Thread(this).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PreDestroy
|
||||||
|
public void shutdown() {
|
||||||
|
try {
|
||||||
|
log.info("Shutting down Socket Gateway.");
|
||||||
|
serverSocket.close();
|
||||||
|
serverUdpSocket.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
|
@ -56,27 +70,52 @@ public class SocketGateway implements Runnable {
|
||||||
serverUdpSocket.bind(new InetSocketAddress(host, udpPort));
|
serverUdpSocket.bind(new InetSocketAddress(host, udpPort));
|
||||||
log.info("Socket Gateway bound UDP on {}:{}", host, udpPort);
|
log.info("Socket Gateway bound UDP on {}:{}", host, udpPort);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
throw new IllegalStateException(e); // Quit; server cannot run if these sockets can't bind.
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
while (!serverSocket.isClosed()) {
|
while (!serverSocket.isClosed()) {
|
||||||
try {
|
try {
|
||||||
Socket clientSocket = serverSocket.accept();
|
Socket clientSocket = serverSocket.accept();
|
||||||
processIncomingConnection(clientSocket);
|
new Thread(() -> processIncomingConnection(clientSocket)).start();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
if (!e.getMessage().equalsIgnoreCase("Socket closed")) e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processIncomingConnection(Socket clientSocket) throws IOException {
|
/**
|
||||||
var din = new DataInputStream(clientSocket.getInputStream());
|
* Logic to do to initialize a client TCP connection, which involves getting
|
||||||
UUID arenaId = new UUID(din.readLong(), din.readLong());
|
* some basic information about the connection, such as which arena the
|
||||||
var oa = arenaStore.getById(arenaId);
|
* client is connecting to. A {@link ClientManager} is then started to
|
||||||
if (oa.isPresent()) {
|
* handle further communication with the client.
|
||||||
new ClientManager(oa.get(), clientSocket).start();
|
* @param clientSocket The socket to the client.
|
||||||
} else {
|
*/
|
||||||
clientSocket.close();
|
private void processIncomingConnection(Socket clientSocket) {
|
||||||
|
try (
|
||||||
|
var in = new DataInputStream(clientSocket.getInputStream());
|
||||||
|
var out = new DataOutputStream(clientSocket.getOutputStream())
|
||||||
|
) {
|
||||||
|
UUID arenaId = new UUID(in.readLong(), in.readLong());
|
||||||
|
UUID clientId;
|
||||||
|
boolean reconnecting = in.readBoolean();
|
||||||
|
if (reconnecting) {
|
||||||
|
clientId = new UUID(in.readLong(), in.readLong());
|
||||||
|
} else {
|
||||||
|
clientId = UUID.randomUUID();
|
||||||
|
}
|
||||||
|
var oa = arenaStore.getById(arenaId);
|
||||||
|
if (oa.isPresent()) {
|
||||||
|
Arena arena = oa.get();
|
||||||
|
ClientManager clientManager = new ClientManager(arena, clientSocket, clientId);
|
||||||
|
arena.registerClient(clientManager);
|
||||||
|
out.writeBoolean(true);
|
||||||
|
clientManager.start();
|
||||||
|
} else {
|
||||||
|
out.writeBoolean(false);
|
||||||
|
clientSocket.close();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,11 +42,11 @@ public class Arena {
|
||||||
return currentStage;
|
return currentStage;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerClient(UUID id, ClientManager clientManager) {
|
public void registerClient(ClientManager clientManager) {
|
||||||
if (clients.containsKey(id)) {
|
if (clients.containsKey(clientManager.getClientId())) {
|
||||||
clientManager.shutdown();
|
clientManager.shutdown();
|
||||||
} else {
|
} else {
|
||||||
clients.put(id, clientManager);
|
clients.put(clientManager.getClientId(), clientManager);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue