Work on #74 Initial logging server example
This commit is contained in:
18
reactor/pom.xml
Normal file
18
reactor/pom.xml
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>com.iluwatar</groupId>
|
||||||
|
<artifactId>java-design-patterns</artifactId>
|
||||||
|
<version>1.5.0</version>
|
||||||
|
</parent>
|
||||||
|
<artifactId>reactor</artifactId>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
42
reactor/src/main/java/com/iluwatar/reactor/App.java
Normal file
42
reactor/src/main/java/com/iluwatar/reactor/App.java
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
package com.iluwatar.reactor;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.channels.SocketChannel;
|
||||||
|
|
||||||
|
import com.iluwatar.reactor.NioReactor.NioChannelEventHandler;
|
||||||
|
|
||||||
|
public class App {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
try {
|
||||||
|
new NioReactor(6666, new LoggingServer()).start();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class LoggingServer implements NioChannelEventHandler {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReadable(SocketChannel channel) {
|
||||||
|
ByteBuffer requestBuffer = ByteBuffer.allocate(1024);
|
||||||
|
try {
|
||||||
|
int byteCount = channel.read(requestBuffer);
|
||||||
|
if (byteCount > 0) {
|
||||||
|
byte[] logRequestContents = new byte[byteCount];
|
||||||
|
byte[] array = requestBuffer.array();
|
||||||
|
System.arraycopy(array, 0, logRequestContents, 0, byteCount);
|
||||||
|
doLogging(new String(logRequestContents));
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doLogging(String log) {
|
||||||
|
// do logging at server side
|
||||||
|
System.out.println(log);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
62
reactor/src/main/java/com/iluwatar/reactor/AppClient.java
Normal file
62
reactor/src/main/java/com/iluwatar/reactor/AppClient.java
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
package com.iluwatar.reactor;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.Socket;
|
||||||
|
|
||||||
|
public class AppClient {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
new LoggingClient("Client 1", 6666).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A logging client that sends logging requests to logging server
|
||||||
|
*/
|
||||||
|
static class LoggingClient {
|
||||||
|
|
||||||
|
private int serverPort;
|
||||||
|
private String clientName;
|
||||||
|
|
||||||
|
public LoggingClient(String clientName, int serverPort) {
|
||||||
|
this.clientName = clientName;
|
||||||
|
this.serverPort = serverPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void start() {
|
||||||
|
Socket socket = null;
|
||||||
|
try {
|
||||||
|
socket = new Socket(InetAddress.getLocalHost(), serverPort);
|
||||||
|
OutputStream outputStream = socket.getOutputStream();
|
||||||
|
PrintWriter writer = new PrintWriter(outputStream);
|
||||||
|
writeLogs(writer);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} finally {
|
||||||
|
if (socket != null) {
|
||||||
|
try {
|
||||||
|
socket.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeLogs(PrintWriter writer) {
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
writer.println(clientName + " - Log request: " + i);
|
||||||
|
try {
|
||||||
|
Thread.sleep(1000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
writer.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
96
reactor/src/main/java/com/iluwatar/reactor/NioReactor.java
Normal file
96
reactor/src/main/java/com/iluwatar/reactor/NioReactor.java
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
package com.iluwatar.reactor;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.nio.channels.SelectionKey;
|
||||||
|
import java.nio.channels.Selector;
|
||||||
|
import java.nio.channels.ServerSocketChannel;
|
||||||
|
import java.nio.channels.SocketChannel;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class NioReactor {
|
||||||
|
|
||||||
|
private int port;
|
||||||
|
private Selector selector;
|
||||||
|
private ServerSocketChannel serverSocketChannel;
|
||||||
|
private NioChannelEventHandler nioEventhandler;
|
||||||
|
|
||||||
|
public NioReactor(int port, NioChannelEventHandler handler) {
|
||||||
|
this.port = port;
|
||||||
|
this.nioEventhandler = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void start() throws IOException {
|
||||||
|
startReactor();
|
||||||
|
requestLoop();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startReactor() throws IOException {
|
||||||
|
selector = Selector.open();
|
||||||
|
serverSocketChannel = ServerSocketChannel.open();
|
||||||
|
serverSocketChannel.socket().bind(new InetSocketAddress(port));
|
||||||
|
serverSocketChannel.configureBlocking(false);
|
||||||
|
SelectionKey acceptorKey = serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
|
||||||
|
acceptorKey.attach(new Acceptor());
|
||||||
|
System.out.println("Reactor started listening on port: " + port);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void requestLoop() throws IOException {
|
||||||
|
while (true) {
|
||||||
|
selector.select();
|
||||||
|
Set<SelectionKey> keys = selector.selectedKeys();
|
||||||
|
for (SelectionKey key : keys) {
|
||||||
|
dispatchEvent(key);
|
||||||
|
}
|
||||||
|
keys.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void dispatchEvent(SelectionKey key) throws IOException {
|
||||||
|
Object handler = key.attachment();
|
||||||
|
if (handler != null) {
|
||||||
|
((EventHandler)handler).handle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface EventHandler {
|
||||||
|
void handle() throws IOException;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Acceptor implements EventHandler {
|
||||||
|
|
||||||
|
public void handle() throws IOException {
|
||||||
|
// non-blocking accept as acceptor will only be called when accept event is available
|
||||||
|
SocketChannel clientChannel = serverSocketChannel.accept();
|
||||||
|
if (clientChannel != null) {
|
||||||
|
new ChannelHandler(clientChannel).handle();
|
||||||
|
}
|
||||||
|
System.out.println("Connection established with a client");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static interface NioChannelEventHandler {
|
||||||
|
void onReadable(SocketChannel channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ChannelHandler implements EventHandler {
|
||||||
|
|
||||||
|
private SocketChannel clientChannel;
|
||||||
|
private SelectionKey selectionKey;
|
||||||
|
|
||||||
|
public ChannelHandler(SocketChannel clientChannel) throws IOException {
|
||||||
|
this.clientChannel = clientChannel;
|
||||||
|
clientChannel.configureBlocking(false);
|
||||||
|
selectionKey = clientChannel.register(selector, 0);
|
||||||
|
selectionKey.attach(this);
|
||||||
|
selectionKey.interestOps(SelectionKey.OP_READ);
|
||||||
|
selector.wakeup();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handle() throws IOException {
|
||||||
|
// only read events are supported.
|
||||||
|
nioEventhandler.onReadable(clientChannel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user