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
|
3. Start server with `CommandClientListener` implementing response creation logic
|
||||||
|
|
||||||
```java
|
```java
|
||||||
Server server = new Server("localhost", port, (socket) -> new CommandClientListener(socket) {
|
CommandServer server = new CommandServer("localhost", port, (socket) -> new CommandClientListener(socket) {
|
||||||
@Override
|
@Override
|
||||||
public AbstractCommand onCommand(AbstractCommand command) {
|
public AbstractCommand onCommand(AbstractCommand command) {
|
||||||
if (command instanceof PingCommand) {
|
if (command instanceof PingCommand) {
|
||||||
|
@ -5,7 +5,7 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
group 'me.bvn13'
|
group 'me.bvn13'
|
||||||
version '1.0'
|
version '1.1'
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
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.
|
* TCP Server.
|
||||||
* Create the instance of this class to connect to {@link Client}
|
* 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();
|
protected final ExecutorService executor = Executors.newCachedThreadPool();
|
||||||
private final List<AbstractClientListener> clients = Collections.synchronizedList(new ArrayList<>());
|
protected final List<T> clients = Collections.synchronizedList(new ArrayList<>());
|
||||||
|
|
||||||
private ServerSocket socket;
|
protected ServerSocket socket;
|
||||||
|
|
||||||
/**
|
protected Server() {
|
||||||
* @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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -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)})
|
* @param clientListenerConstructor to provide constructor for client listener (see {@link me.bvn13.sewy.Server#Server(java.lang.String, int, java.lang.Class)})
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@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");
|
log.debug("Starting server");
|
||||||
executor.execute(() -> {
|
executor.execute(() -> {
|
||||||
try (final ServerSocket server = new ServerSocket(port, 0, InetAddress.getByName(host))) {
|
try (final ServerSocket server = new ServerSocket(port, 0, InetAddress.getByName(host))) {
|
||||||
@ -79,7 +74,7 @@ public class Server {
|
|||||||
|
|
||||||
while (!server.isClosed()) {
|
while (!server.isClosed()) {
|
||||||
final Socket client = server.accept();
|
final Socket client = server.accept();
|
||||||
final AbstractClientListener clientListener = clientListenerConstructor.apply(client);
|
final T clientListener = clientListenerConstructor.apply(client);
|
||||||
executor.execute(clientListener);
|
executor.execute(clientListener);
|
||||||
clients.add(clientListener);
|
clients.add(clientListener);
|
||||||
}
|
}
|
||||||
@ -97,7 +92,7 @@ public class Server {
|
|||||||
*/
|
*/
|
||||||
public void stop() {
|
public void stop() {
|
||||||
log.debug("Stopping server");
|
log.debug("Stopping server");
|
||||||
final Iterator<AbstractClientListener> iterator = clients.iterator();
|
final Iterator<T> iterator = clients.iterator();
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
final AbstractClientListener client = iterator.next();
|
final AbstractClientListener client = iterator.next();
|
||||||
client.stop();
|
client.stop();
|
||||||
|
@ -31,7 +31,7 @@ public class ServerTest {
|
|||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@ValueSource(ints = START_PORT + 1)
|
@ValueSource(ints = START_PORT + 1)
|
||||||
void testServerStarts(int port) throws InterruptedException {
|
void testServerStarts(int port) throws InterruptedException {
|
||||||
Server server = new Server("localhost", port);
|
Server server = new Server("localhost", port, SimpleClientListener.class);
|
||||||
Thread.sleep(1000);
|
Thread.sleep(1000);
|
||||||
Assertions.assertTrue(server.isListening());
|
Assertions.assertTrue(server.isListening());
|
||||||
server.stop();
|
server.stop();
|
||||||
@ -40,7 +40,7 @@ public class ServerTest {
|
|||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@ValueSource(ints = START_PORT + 2)
|
@ValueSource(ints = START_PORT + 2)
|
||||||
void givenServerRunning_whenClientConnects_thenServerCanStopClientListener(int port) throws InterruptedException {
|
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);
|
Client<SimpleClientListener> client = new Client<>("localhost", port, SimpleClientListener.class);
|
||||||
Thread.sleep(1000);
|
Thread.sleep(1000);
|
||||||
Assertions.assertTrue(server.isListening());
|
Assertions.assertTrue(server.isListening());
|
||||||
@ -85,7 +85,7 @@ public class ServerTest {
|
|||||||
Sewy.register(PingCommand.class);
|
Sewy.register(PingCommand.class);
|
||||||
Sewy.register(PongCommand.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
|
@Override
|
||||||
public AbstractCommand onCommand(AbstractCommand command) {
|
public AbstractCommand onCommand(AbstractCommand command) {
|
||||||
if (command instanceof PingCommand) {
|
if (command instanceof PingCommand) {
|
||||||
|
Loading…
Reference in New Issue
Block a user