implemented CommandServer
This commit is contained in:
parent
e0fe404832
commit
8fbc693a99
@ -51,7 +51,7 @@ Sewy.register(PongCommand.class);
|
||||
3. Start server with `CommandClientListener` implementing response creation logic
|
||||
|
||||
```java
|
||||
Server server = new Server("localhost", port, (socket) -> new CommandClientListener(socket) {
|
||||
CommandServer server = new CommandServer("localhost", port, (socket) -> new CommandClientListener(socket) {
|
||||
@Override
|
||||
public AbstractCommand onCommand(AbstractCommand command) {
|
||||
if (command instanceof PingCommand) {
|
||||
|
@ -5,7 +5,7 @@ plugins {
|
||||
}
|
||||
|
||||
group 'me.bvn13'
|
||||
version '1.0'
|
||||
version '1.1'
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
|
100
src/main/java/me/bvn13/sewy/CommandServer.java
Normal file
100
src/main/java/me/bvn13/sewy/CommandServer.java
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
Copyright 2022 Vyacheslav Boyko
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
package me.bvn13.sewy;
|
||||
|
||||
import me.bvn13.sewy.command.AbstractCommand;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static java.lang.String.format;
|
||||
import static me.bvn13.sewy.ClientListenerFactory.createClientListenerConstructor;
|
||||
|
||||
/**
|
||||
* TCP Server.
|
||||
* Works with command protocol.
|
||||
* Create the instance of this class to connect to {@link Client}
|
||||
*/
|
||||
public class CommandServer extends Server<CommandClientListener> {
|
||||
|
||||
/**
|
||||
* @param host host to bind in order to start listen to clients
|
||||
* @param port port to start listen to
|
||||
*/
|
||||
public CommandServer(String host, int port) {
|
||||
this(host, port, CommandClientListener.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param host host to bind in order to start listen to clients
|
||||
* @param port port to start listen to
|
||||
* @param clientListenerClass client listen class to be used for communication
|
||||
*/
|
||||
public CommandServer(String host, int port, Class clientListenerClass) {
|
||||
this(host, port, createClientListenerConstructor(clientListenerClass));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param host host to bind in order to start listen to clients
|
||||
* @param port port to start listen to
|
||||
* @param clientListenerConstructor to provide constructor for client listener (see {@link CommandServer#CommandServer(String, int, Class)})
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public CommandServer(String host, int port, Function<Socket, CommandClientListener> clientListenerConstructor) {
|
||||
log.debug("Starting server");
|
||||
executor.execute(() -> {
|
||||
try (final ServerSocket server = new ServerSocket(port, 0, InetAddress.getByName(host))) {
|
||||
|
||||
socket = server;
|
||||
|
||||
while (!server.isClosed()) {
|
||||
final Socket client = server.accept();
|
||||
final CommandClientListener clientListener = clientListenerConstructor.apply(client);
|
||||
executor.execute(clientListener);
|
||||
clients.add(clientListener);
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
log.error(format("Error while conversation with %s:%d", host, port), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends command to every client
|
||||
* @param command command to be sent
|
||||
* @param <T> generic type
|
||||
*/
|
||||
public <T extends AbstractCommand> void send(T command) {
|
||||
log.debug("Start to send command: " + command);
|
||||
for (CommandClientListener client : clients) {
|
||||
client.send(command);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -37,21 +37,16 @@ import static me.bvn13.sewy.ClientListenerFactory.createClientListenerConstructo
|
||||
* TCP Server.
|
||||
* Create the instance of this class to connect to {@link Client}
|
||||
*/
|
||||
public class Server {
|
||||
public class Server<T extends AbstractClientListener> {
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(this.getClass());
|
||||
protected final Logger log = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
private final ExecutorService executor = Executors.newCachedThreadPool();
|
||||
private final List<AbstractClientListener> clients = Collections.synchronizedList(new ArrayList<>());
|
||||
protected final ExecutorService executor = Executors.newCachedThreadPool();
|
||||
protected final List<T> clients = Collections.synchronizedList(new ArrayList<>());
|
||||
|
||||
private ServerSocket socket;
|
||||
protected ServerSocket socket;
|
||||
|
||||
/**
|
||||
* @param host host to bind in order to start listen to clients
|
||||
* @param port port to start listen to
|
||||
*/
|
||||
public Server(String host, int port) {
|
||||
this(host, port, CommandClientListener.class);
|
||||
protected Server() {
|
||||
}
|
||||
|
||||
/**
|
||||
@ -70,7 +65,7 @@ public class Server {
|
||||
* @param clientListenerConstructor to provide constructor for client listener (see {@link me.bvn13.sewy.Server#Server(java.lang.String, int, java.lang.Class)})
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Server(String host, int port, Function<Socket, CommandClientListener> clientListenerConstructor) {
|
||||
public Server(String host, int port, Function<Socket, T> clientListenerConstructor) {
|
||||
log.debug("Starting server");
|
||||
executor.execute(() -> {
|
||||
try (final ServerSocket server = new ServerSocket(port, 0, InetAddress.getByName(host))) {
|
||||
@ -79,7 +74,7 @@ public class Server {
|
||||
|
||||
while (!server.isClosed()) {
|
||||
final Socket client = server.accept();
|
||||
final AbstractClientListener clientListener = clientListenerConstructor.apply(client);
|
||||
final T clientListener = clientListenerConstructor.apply(client);
|
||||
executor.execute(clientListener);
|
||||
clients.add(clientListener);
|
||||
}
|
||||
@ -97,7 +92,7 @@ public class Server {
|
||||
*/
|
||||
public void stop() {
|
||||
log.debug("Stopping server");
|
||||
final Iterator<AbstractClientListener> iterator = clients.iterator();
|
||||
final Iterator<T> iterator = clients.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
final AbstractClientListener client = iterator.next();
|
||||
client.stop();
|
||||
|
@ -31,7 +31,7 @@ public class ServerTest {
|
||||
@ParameterizedTest
|
||||
@ValueSource(ints = START_PORT + 1)
|
||||
void testServerStarts(int port) throws InterruptedException {
|
||||
Server server = new Server("localhost", port);
|
||||
Server server = new Server("localhost", port, SimpleClientListener.class);
|
||||
Thread.sleep(1000);
|
||||
Assertions.assertTrue(server.isListening());
|
||||
server.stop();
|
||||
@ -40,7 +40,7 @@ public class ServerTest {
|
||||
@ParameterizedTest
|
||||
@ValueSource(ints = START_PORT + 2)
|
||||
void givenServerRunning_whenClientConnects_thenServerCanStopClientListener(int port) throws InterruptedException {
|
||||
Server server = new Server("localhost", port);
|
||||
Server server = new Server("localhost", port, SimpleClientListener.class);
|
||||
Client<SimpleClientListener> client = new Client<>("localhost", port, SimpleClientListener.class);
|
||||
Thread.sleep(1000);
|
||||
Assertions.assertTrue(server.isListening());
|
||||
@ -85,7 +85,7 @@ public class ServerTest {
|
||||
Sewy.register(PingCommand.class);
|
||||
Sewy.register(PongCommand.class);
|
||||
|
||||
Server server = new Server("localhost", port, (socket) -> new CommandClientListener(socket) {
|
||||
CommandServer server = new CommandServer("localhost", port, (socket) -> new CommandClientListener(socket) {
|
||||
@Override
|
||||
public AbstractCommand onCommand(AbstractCommand command) {
|
||||
if (command instanceof PingCommand) {
|
||||
|
Loading…
Reference in New Issue
Block a user