Work on #74 Initial logging server example
This commit is contained in:
parent
da6d92d125
commit
99adb5b0cf
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);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user