Reworked NetworkingClientManager into SRP model.

This commit is contained in:
lieght
2025-10-14 23:27:12 +02:00
parent cb7e3298fd
commit 8f7e78efb5
13 changed files with 221 additions and 257 deletions

View File

@@ -2,26 +2,24 @@ package org.toop;
import org.toop.app.App; import org.toop.app.App;
import org.toop.framework.audio.*; import org.toop.framework.audio.*;
import org.toop.framework.networking.NetworkingClientEventListener;
import org.toop.framework.networking.NetworkingClientManager; import org.toop.framework.networking.NetworkingClientManager;
import org.toop.framework.networking.NetworkingInitializationException;
import org.toop.framework.resource.ResourceLoader; import org.toop.framework.resource.ResourceLoader;
import org.toop.framework.resource.ResourceManager; import org.toop.framework.resource.ResourceManager;
import org.toop.framework.resource.ResourceMeta;
import org.toop.framework.resource.resources.MusicAsset; import org.toop.framework.resource.resources.MusicAsset;
import org.toop.framework.resource.resources.SoundEffectAsset; import org.toop.framework.resource.resources.SoundEffectAsset;
import java.util.Arrays;
import java.util.List;
public final class Main { public final class Main {
static void main(String[] args) { static void main(String[] args) throws InterruptedException {
initSystems(); initSystems();
Thread.sleep(200);
App.run(args); App.run(args);
} }
private static void initSystems() throws NetworkingInitializationException { private static void initSystems() {
ResourceManager.loadAssets(new ResourceLoader("app/src/main/resources/assets")); ResourceManager.loadAssets(new ResourceLoader("app/src/main/resources/assets"));
new Thread(NetworkingClientManager::new).start(); new Thread(() -> new NetworkingClientEventListener(new NetworkingClientManager())).start();
new Thread(() -> { new Thread(() -> {
MusicManager<MusicAsset> musicManager = new MusicManager<>(ResourceManager.getAllOfTypeAndRemoveWrapper(MusicAsset.class), true); MusicManager<MusicAsset> musicManager = new MusicManager<>(ResourceManager.getAllOfTypeAndRemoveWrapper(MusicAsset.class), true);
SoundEffectManager<SoundEffectAsset> soundEffectManager = new SoundEffectManager<>(ResourceManager.getAllOfType(SoundEffectAsset.class)); SoundEffectManager<SoundEffectAsset> soundEffectManager = new SoundEffectManager<>(ResourceManager.getAllOfType(SoundEffectAsset.class));

View File

@@ -19,6 +19,7 @@ import org.toop.app.layer.containers.HorizontalContainer;
import org.toop.app.layer.containers.VerticalContainer; import org.toop.app.layer.containers.VerticalContainer;
import org.toop.app.layer.layers.game.TicTacToeLayer; import org.toop.app.layer.layers.game.TicTacToeLayer;
import org.toop.framework.eventbus.EventFlow; import org.toop.framework.eventbus.EventFlow;
import org.toop.framework.networking.clients.TournamentNetworkingClient;
import org.toop.framework.networking.events.NetworkEvents; import org.toop.framework.networking.events.NetworkEvents;
import org.toop.local.AppContext; import org.toop.local.AppContext;
@@ -111,6 +112,7 @@ public final class ConnectedLayer extends Layer {
new EventFlow() new EventFlow()
.addPostEvent( .addPostEvent(
NetworkEvents.StartClient.class, NetworkEvents.StartClient.class,
TournamentNetworkingClient.class,
information.serverIP(), information.serverIP(),
Integer.parseInt(information.serverPort())) Integer.parseInt(information.serverPort()))
.onResponse( .onResponse(

View File

@@ -134,7 +134,8 @@ public final class GlobalEventBus {
for (Consumer<? super EventType> listener : classListeners) { for (Consumer<? super EventType> listener : classListeners) {
try { try {
listener.accept(event); listener.accept(event);
} catch (Throwable ignored) { } catch (Throwable e) {
// e.printStackTrace();
} }
} }
} }
@@ -146,7 +147,8 @@ public final class GlobalEventBus {
for (Consumer<? super EventType> listener : genericListeners) { for (Consumer<? super EventType> listener : genericListeners) {
try { try {
listener.accept(event); listener.accept(event);
} catch (Throwable ignored) { } catch (Throwable e) {
// e.printStackTrace();
} }
} }
} }

View File

@@ -0,0 +1,126 @@
package org.toop.framework.networking;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.toop.framework.eventbus.EventFlow;
import org.toop.framework.networking.interfaces.NetworkingClient;
import org.toop.framework.networking.events.NetworkEvents;
import org.toop.framework.networking.interfaces.NetworkingClientManager;
public class NetworkingClientEventListener {
private static final Logger logger = LogManager.getLogger(NetworkingClientEventListener.class);
private final NetworkingClientManager clientManager;
/** Starts a connection manager, to manage, connections. */
public NetworkingClientEventListener(NetworkingClientManager clientManager) {
this.clientManager = clientManager;
new EventFlow()
.listen(this::handleStartClient)
.listen(this::handleCommand)
.listen(this::handleSendLogin)
.listen(this::handleSendLogout)
.listen(this::handleSendGetPlayerlist)
.listen(this::handleSendGetGamelist)
.listen(this::handleSendSubscribe)
.listen(this::handleSendMove)
.listen(this::handleSendChallenge)
.listen(this::handleSendAcceptChallenge)
.listen(this::handleSendForfeit)
.listen(this::handleSendMessage)
.listen(this::handleSendHelp)
.listen(this::handleSendHelpForCommand)
.listen(this::handleCloseClient)
.listen(this::handleChangeClientHost)
.listen(this::handleGetAllConnections)
.listen(this::handleShutdownAll);
}
void handleStartClient(NetworkEvents.StartClient<? extends NetworkingClient> event) {
long clientId = clientManager.startClient(event.networkingClientClass(), event.host(), event.port()).orElse(-1);
logger.info("Client {} started", clientId);
try {
new EventFlow()
.addPostEvent(new NetworkEvents.StartClientResponse(clientId, event.getIdentifier()))
.asyncPostEvent();
} catch (Exception e) {
e.printStackTrace();
}
}
void handleCommand(NetworkEvents.SendCommand event) {
String args = String.join(" ", event.args());
logger.error(args);
clientManager.sendCommand(event.clientId(), args);
}
void handleSendLogin(NetworkEvents.SendLogin event) {
logger.error("{}", event.username());
clientManager.sendCommand(event.clientId(), String.format("LOGIN %s", event.username()));
}
private void handleSendLogout(NetworkEvents.SendLogout event) {
clientManager.sendCommand(event.clientId(), "LOGOUT");
}
private void handleSendGetPlayerlist(NetworkEvents.SendGetPlayerlist event) {
clientManager.sendCommand(event.clientId(), "GET PLAYERLIST");
}
private void handleSendGetGamelist(NetworkEvents.SendGetGamelist event) {
clientManager.sendCommand(event.clientId(), "GET GAMELIST");
}
private void handleSendSubscribe(NetworkEvents.SendSubscribe event) {
clientManager.sendCommand(event.clientId(), String.format("SUBSCRIBE %s", event.gameType()));
}
private void handleSendMove(NetworkEvents.SendMove event) {
clientManager.sendCommand(event.clientId(), String.format("MOVE %d", event.moveNumber()));
}
private void handleSendChallenge(NetworkEvents.SendChallenge event) {
clientManager.sendCommand(
event.clientId(),
String.format("CHALLENGE %s %s", event.usernameToChallenge(), event.gameType()));
}
private void handleSendAcceptChallenge(NetworkEvents.SendAcceptChallenge event) {
clientManager.sendCommand(event.clientId(), String.format("CHALLENGE ACCEPT %d", event.challengeId()));
}
private void handleSendForfeit(NetworkEvents.SendForfeit event) {
clientManager.sendCommand(event.clientId(), "FORFEIT");
}
private void handleSendMessage(NetworkEvents.SendMessage event) {
clientManager.sendCommand(event.clientId(), String.format("MESSAGE %s", event.message()));
}
private void handleSendHelp(NetworkEvents.SendHelp event) {
clientManager.sendCommand(event.clientId(), "HELP");
}
private void handleSendHelpForCommand(NetworkEvents.SendHelpForCommand event) {
clientManager.sendCommand(event.clientId(), String.format("HELP %s", event.command()));
}
private void handleChangeClientHost(NetworkEvents.ChangeClientHost event) {
// NetworkingClient client = this.networkClients.get(event.clientId());
// client.closeConnection();
// startClientRequest(event.ip(), event.port(), event.clientId());
}
void handleCloseClient(NetworkEvents.CloseClient event) {
this.clientManager.closeClient(event.clientId());
}
void handleGetAllConnections(NetworkEvents.RequestsAllClients request) {
// List<NetworkingClient> a = new ArrayList<>(this.networkClients.values());
// request.future().complete(a);
}
public void handleShutdownAll(NetworkEvents.ForceCloseAllClients request) {
// TODO
}
}

View File

@@ -5,193 +5,57 @@ import java.util.concurrent.ConcurrentHashMap;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.toop.framework.SnowflakeGenerator; import org.toop.framework.SnowflakeGenerator;
import org.toop.framework.eventbus.EventFlow; import org.toop.framework.networking.interfaces.NetworkingClient;
import org.toop.framework.networking.events.NetworkEvents;
public class NetworkingClientManager {
public class NetworkingClientManager implements org.toop.framework.networking.interfaces.NetworkingClientManager {
private static final Logger logger = LogManager.getLogger(NetworkingClientManager.class); private static final Logger logger = LogManager.getLogger(NetworkingClientManager.class);
private final Map<Long, NetworkingClient> networkClients = new ConcurrentHashMap<>();
/** Map of serverId -> Server instances */ public NetworkingClientManager() {}
final Map<Long, NetworkingClient> networkClients = new ConcurrentHashMap<>();
/** Starts a connection manager, to manage, connections. */ @Override
public NetworkingClientManager() throws NetworkingInitializationException { public OptionalLong startClient(Class<? extends NetworkingClient> networkingClientClass, String host, int port) {
long clientId = SnowflakeGenerator.nextId();
try { try {
new EventFlow() NetworkingClient networkingClient = networkingClientClass
.listen(this::handleStartClient) .getConstructor(long.class, String.class, int.class).newInstance(clientId, host, port);
.listen(this::handleCommand) this.networkClients.put(clientId, networkingClient);
.listen(this::handleSendLogin) logger.info("New client started successfully for {}:{}", host, port);
.listen(this::handleSendLogout)
.listen(this::handleSendGetPlayerlist)
.listen(this::handleSendGetGamelist)
.listen(this::handleSendSubscribe)
.listen(this::handleSendMove)
.listen(this::handleSendChallenge)
.listen(this::handleSendAcceptChallenge)
.listen(this::handleSendForfeit)
.listen(this::handleSendMessage)
.listen(this::handleSendHelp)
.listen(this::handleSendHelpForCommand)
.listen(this::handleCloseClient)
.listen(this::handleChangeClientHost)
.listen(this::handleGetAllConnections)
.listen(this::handleShutdownAll);
logger.info("NetworkingClientManager initialized");
} catch (Exception e) { } catch (Exception e) {
logger.error("Failed to initialize the client manager", e); logger.error(e); // TODO Better error handling
throw e; return OptionalLong.empty();
} }
return OptionalLong.of(clientId);
} }
long startClientRequest(String ip, int port) { @Override
long connectionId = SnowflakeGenerator.nextId(); public boolean sendCommand(long id, String command) {
try { logger.info("Sending command to client for {}:{}", id, command);
NetworkingClient client = if (command.isEmpty()) { return false; }
new NetworkingClient(
() -> new NetworkingGameClientHandler(connectionId), NetworkingClient client = this.networkClients.get(id);
ip, if (client == null) { return false; } // TODO: Create client not found exceptions.
port,
connectionId); String toSend = command.trim();
client.setConnectionId(connectionId);
this.networkClients.put(connectionId, client); if (toSend.endsWith("\n")) { client.writeAndFlush(toSend); }
logger.info("New client started successfully for {}:{}", ip, port); else { client.writeAndFlush(toSend + "\n"); }
} catch (Exception e) {
logger.error(e); return true;
}
return connectionId;
} }
private long startClientRequest(String ip, int port, long clientId) { @Override
try { // With EventFlow public boolean reconnect(long id) {
NetworkingClient client = return false; // TODO
new NetworkingClient(
() -> new NetworkingGameClientHandler(clientId), ip, port, clientId);
client.setConnectionId(clientId);
this.networkClients.replace(clientId, client);
logger.info(
"New client started successfully for {}:{}, replaced: {}", ip, port, clientId);
} catch (Exception e) {
logger.error(e);
}
logger.info("Client {} started", clientId);
return clientId;
} }
void handleStartClient(NetworkEvents.StartClient event) { @Override
long id = this.startClientRequest(event.ip(), event.port()); public boolean changeAddress(long id, String host, int port) {
new Thread( return false; // TODO
() ->
new EventFlow()
.addPostEvent(
NetworkEvents.StartClientResponse.class,
id,
event.eventSnowflake())
.asyncPostEvent())
.start();
} }
void handleCommand( @Override
NetworkEvents.SendCommand public boolean closeClient(long id) {
event) { // TODO: Move this to ServerConnection class, keep it internal. return false; // TODO
NetworkingClient client = this.networkClients.get(event.clientId());
String args = String.join(" ", event.args());
sendCommand(client, args);
}
void handleSendLogin(NetworkEvents.SendLogin event) {
NetworkingClient client = this.networkClients.get(event.clientId());
sendCommand(client, String.format("LOGIN %s", event.username()));
}
private void handleSendLogout(NetworkEvents.SendLogout event) {
NetworkingClient client = this.networkClients.get(event.clientId());
sendCommand(client, "LOGOUT");
}
private void handleSendGetPlayerlist(NetworkEvents.SendGetPlayerlist event) {
NetworkingClient client = this.networkClients.get(event.clientId());
sendCommand(client, "GET PLAYERLIST");
}
private void handleSendGetGamelist(NetworkEvents.SendGetGamelist event) {
NetworkingClient client = this.networkClients.get(event.clientId());
sendCommand(client, "GET GAMELIST");
}
private void handleSendSubscribe(NetworkEvents.SendSubscribe event) {
NetworkingClient client = this.networkClients.get(event.clientId());
sendCommand(client, String.format("SUBSCRIBE %s", event.gameType()));
}
private void handleSendMove(NetworkEvents.SendMove event) {
NetworkingClient client = this.networkClients.get(event.clientId());
sendCommand(client, String.format("MOVE %d", event.moveNumber()));
}
private void handleSendChallenge(NetworkEvents.SendChallenge event) {
NetworkingClient client = this.networkClients.get(event.clientId());
sendCommand(
client,
String.format("CHALLENGE %s %s", event.usernameToChallenge(), event.gameType()));
}
private void handleSendAcceptChallenge(NetworkEvents.SendAcceptChallenge event) {
NetworkingClient client = this.networkClients.get(event.clientId());
sendCommand(client, String.format("CHALLENGE ACCEPT %d", event.challengeId()));
}
private void handleSendForfeit(NetworkEvents.SendForfeit event) {
NetworkingClient client = this.networkClients.get(event.clientId());
sendCommand(client, "FORFEIT");
}
private void handleSendMessage(NetworkEvents.SendMessage event) {
NetworkingClient client = this.networkClients.get(event.clientId());
sendCommand(client, String.format("MESSAGE %s", event.message()));
}
private void handleSendHelp(NetworkEvents.SendHelp event) {
NetworkingClient client = this.networkClients.get(event.clientId());
sendCommand(client, "HELP");
}
private void handleSendHelpForCommand(NetworkEvents.SendHelpForCommand event) {
NetworkingClient client = this.networkClients.get(event.clientId());
sendCommand(client, String.format("HELP %s", event.command()));
}
private void sendCommand(NetworkingClient client, String command) {
logger.info(
"Preparing to send command: {} to server: {}:{}. clientId: {}",
command.trim(),
client.getHost(),
client.getPort(),
client.getId());
client.writeAndFlushnl(command);
}
private void handleChangeClientHost(NetworkEvents.ChangeClientHost event) {
NetworkingClient client = this.networkClients.get(event.clientId());
client.closeConnection();
startClientRequest(event.ip(), event.port(), event.clientId());
}
void handleCloseClient(NetworkEvents.CloseClient event) {
NetworkingClient client = this.networkClients.get(event.clientId());
client.closeConnection();
this.networkClients.remove(event.clientId());
logger.info("Client {} closed successfully.", event.clientId());
}
void handleGetAllConnections(NetworkEvents.RequestsAllClients request) {
List<NetworkingClient> a = new ArrayList<>(this.networkClients.values());
request.future().complete(a);
}
public void handleShutdownAll(NetworkEvents.ForceCloseAllClients request) {
this.networkClients.values().forEach(NetworkingClient::closeConnection);
this.networkClients.clear();
logger.info("All servers shut down");
} }
} }

View File

@@ -1,4 +1,4 @@
package org.toop.framework.networking; package org.toop.framework.networking.clients;
import io.netty.bootstrap.Bootstrap; import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*; import io.netty.channel.*;
@@ -9,27 +9,16 @@ import io.netty.handler.codec.LineBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder; import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder; import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.CharsetUtil; import io.netty.util.CharsetUtil;
import java.util.function.Supplier;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.toop.framework.eventbus.EventFlow; import org.toop.framework.networking.handlers.NetworkingGameClientHandler;
import org.toop.framework.networking.events.NetworkEvents; import org.toop.framework.networking.interfaces.NetworkingClient;
public class NetworkingClient { public class TournamentNetworkingClient implements NetworkingClient {
private static final Logger logger = LogManager.getLogger(NetworkingClient.class); private static final Logger logger = LogManager.getLogger(TournamentNetworkingClient.class);
private long connectionId;
private String host;
private int port;
private Channel channel; private Channel channel;
private NetworkingGameClientHandler handler;
public NetworkingClient( public TournamentNetworkingClient(long clientId, String host, int port) {
Supplier<NetworkingGameClientHandler> handlerFactory,
String host,
int port,
long connectionId) {
this.connectionId = connectionId;
try { try {
Bootstrap bootstrap = new Bootstrap(); Bootstrap bootstrap = new Bootstrap();
EventLoopGroup workerGroup = new MultiThreadIoEventLoopGroup(NioIoHandler.newFactory()); EventLoopGroup workerGroup = new MultiThreadIoEventLoopGroup(NioIoHandler.newFactory());
@@ -40,7 +29,7 @@ public class NetworkingClient {
new ChannelInitializer<SocketChannel>() { new ChannelInitializer<SocketChannel>() {
@Override @Override
public void initChannel(SocketChannel ch) { public void initChannel(SocketChannel ch) {
handler = handlerFactory.get(); NetworkingGameClientHandler handler = new NetworkingGameClientHandler(clientId);
ChannelPipeline pipeline = ch.pipeline(); ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new LineBasedFrameDecoder(1024)); // split at \n pipeline.addLast(new LineBasedFrameDecoder(1024)); // split at \n
@@ -52,53 +41,28 @@ public class NetworkingClient {
}); });
ChannelFuture channelFuture = bootstrap.connect(host, port).sync(); ChannelFuture channelFuture = bootstrap.connect(host, port).sync();
this.channel = channelFuture.channel(); this.channel = channelFuture.channel();
this.host = host;
this.port = port;
} catch (Exception e) { } catch (Exception e) {
logger.error("Failed to create networking client instance", e); logger.error("Failed to create networking client instance", e);
} }
} }
public NetworkingGameClientHandler getHandler() { @Override
return this.handler; public boolean isActive() {
}
public String getHost() {
return this.host;
}
public int getPort() {
return this.port;
}
public void setConnectionId(long connectionId) {
this.connectionId = connectionId;
}
public boolean isChannelActive() {
return this.channel != null && this.channel.isActive(); return this.channel != null && this.channel.isActive();
} }
@Override
public void writeAndFlush(String msg) { public void writeAndFlush(String msg) {
String literalMsg = msg.replace("\n", "\\n").replace("\r", "\\r"); String literalMsg = msg.replace("\n", "\\n").replace("\r", "\\r");
if (isChannelActive()) { if (isActive()) {
this.channel.writeAndFlush(msg); this.channel.writeAndFlush(msg);
logger.info( logger.info("Connection {} sent message: '{}' ", this.channel.remoteAddress(), literalMsg);
"Connection {} sent message: '{}' ", this.channel.remoteAddress(), literalMsg);
} else { } else {
logger.warn("Cannot send message: '{}', connection inactive. ", literalMsg); logger.warn("Cannot send message: '{}', connection inactive. ", literalMsg);
} }
} }
public void writeAndFlushnl(String msg) { @Override
if (isChannelActive()) {
this.channel.writeAndFlush(msg + "\r\n");
logger.info("Connection {} sent message: '{}'", this.channel.remoteAddress(), msg);
} else {
logger.warn("Cannot send message: '{}', connection inactive.", msg);
}
}
public void closeConnection() { public void closeConnection() {
if (this.channel != null && this.channel.isActive()) { if (this.channel != null && this.channel.isActive()) {
this.channel this.channel
@@ -109,11 +73,6 @@ public class NetworkingClient {
logger.info( logger.info(
"Connection {} closed successfully", "Connection {} closed successfully",
this.channel.remoteAddress()); this.channel.remoteAddress());
new EventFlow()
.addPostEvent(
new NetworkEvents.ClosedConnection(
this.connectionId))
.asyncPostEvent();
} else { } else {
logger.error( logger.error(
"Error closing connection {}. Error: {}", "Error closing connection {}. Error: {}",
@@ -123,8 +82,4 @@ public class NetworkingClient {
}); });
} }
} }
public long getId() {
return this.connectionId;
}
} }

View File

@@ -8,7 +8,7 @@ import org.toop.framework.eventbus.events.ResponseToUniqueEvent;
import org.toop.framework.eventbus.events.UniqueEvent; import org.toop.framework.eventbus.events.UniqueEvent;
import org.toop.framework.eventbus.events.EventsBase; import org.toop.framework.eventbus.events.EventsBase;
import org.toop.annotations.AutoResponseResult; import org.toop.annotations.AutoResponseResult;
import org.toop.framework.networking.NetworkingClient; import org.toop.framework.networking.interfaces.NetworkingClient;
/** /**
* A collection of networking-related event records for use with the {@link * A collection of networking-related event records for use with the {@link
@@ -106,11 +106,16 @@ public class NetworkEvents extends EventsBase {
* *
* <p>Carries IP, port, and a unique event ID for correlation with responses. * <p>Carries IP, port, and a unique event ID for correlation with responses.
* *
* @param ip Server IP address. * @param networkingClientClass The type of networking client to create.
* @param host Server IP address.
* @param port Server port. * @param port Server port.
* @param eventSnowflake Unique event identifier for correlation. * @param eventSnowflake Unique event identifier for correlation.
*/ */
public record StartClient(String ip, int port, long eventSnowflake) implements UniqueEvent {} public record StartClient<T extends NetworkingClient>(
Class<T> networkingClientClass,
String host,
int port,
long identifier) implements UniqueEvent {}
/** /**
* Response confirming a client was started. * Response confirming a client was started.

View File

@@ -1,4 +1,4 @@
package org.toop.framework.networking; package org.toop.framework.networking.handlers;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInboundHandlerAdapter;

View File

@@ -1,12 +0,0 @@
//package org.toop.frontend.networking.handlers;
//
//import io.netty.channel.ChannelHandlerContext;
//import org.apache.logging.log4j.LogManager;
//import org.apache.logging.log4j.Logger;
//import org.toop.frontend.networking.NetworkingGameClientHandler;
//
//public class NetworkingTicTacToeClientHandler extends NetworkingGameClientHandler {
// static final Logger logger = LogManager.getLogger(NetworkingTicTacToeClientHandler.class);
//
//
//}

View File

@@ -0,0 +1,7 @@
package org.toop.framework.networking.interfaces;
public interface NetworkingClient {
boolean isActive();
void writeAndFlush(String msg);
void closeConnection();
}

View File

@@ -0,0 +1,11 @@
package org.toop.framework.networking.interfaces;
import java.util.OptionalLong;
public interface NetworkingClientManager {
OptionalLong startClient(Class<? extends NetworkingClient> networkingClientClass, String host, int port);
boolean sendCommand(long id, String command);
boolean reconnect(long id);
boolean changeAddress(long id, String host, int port);
boolean closeClient(long id);
}

View File

@@ -0,0 +1,3 @@
package org.toop.framework.networking.types;
public record ServerCommand(long clientId, String command) {}

View File

@@ -0,0 +1,3 @@
package org.toop.framework.networking.types;
public record ServerMessage(String message) {}