Work on #74 Initial logging server example

This commit is contained in:
Narendra Pathai 2015-08-23 11:48:57 +05:30
parent da6d92d125
commit 99adb5b0cf
4 changed files with 218 additions and 0 deletions

18
reactor/pom.xml Normal file
View 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>

View 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);
}
}
}

View 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();
}
}
}
}

View 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);
}
}
}