Skip to content

Commit 99adb5b

Browse files
committed
Work on iluwatar#74 Initial logging server example
1 parent da6d92d commit 99adb5b

File tree

4 files changed

+218
-0
lines changed

4 files changed

+218
-0
lines changed

reactor/pom.xml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?xml version="1.0"?>
2+
<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"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
4+
<modelVersion>4.0.0</modelVersion>
5+
<parent>
6+
<groupId>com.iluwatar</groupId>
7+
<artifactId>java-design-patterns</artifactId>
8+
<version>1.5.0</version>
9+
</parent>
10+
<artifactId>reactor</artifactId>
11+
<dependencies>
12+
<dependency>
13+
<groupId>junit</groupId>
14+
<artifactId>junit</artifactId>
15+
<scope>test</scope>
16+
</dependency>
17+
</dependencies>
18+
</project>
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package com.iluwatar.reactor;
2+
3+
import java.io.IOException;
4+
import java.nio.ByteBuffer;
5+
import java.nio.channels.SocketChannel;
6+
7+
import com.iluwatar.reactor.NioReactor.NioChannelEventHandler;
8+
9+
public class App {
10+
11+
public static void main(String[] args) {
12+
try {
13+
new NioReactor(6666, new LoggingServer()).start();
14+
} catch (IOException e) {
15+
e.printStackTrace();
16+
}
17+
}
18+
19+
static class LoggingServer implements NioChannelEventHandler {
20+
21+
@Override
22+
public void onReadable(SocketChannel channel) {
23+
ByteBuffer requestBuffer = ByteBuffer.allocate(1024);
24+
try {
25+
int byteCount = channel.read(requestBuffer);
26+
if (byteCount > 0) {
27+
byte[] logRequestContents = new byte[byteCount];
28+
byte[] array = requestBuffer.array();
29+
System.arraycopy(array, 0, logRequestContents, 0, byteCount);
30+
doLogging(new String(logRequestContents));
31+
}
32+
} catch (IOException e) {
33+
e.printStackTrace();
34+
}
35+
}
36+
37+
private void doLogging(String log) {
38+
// do logging at server side
39+
System.out.println(log);
40+
}
41+
}
42+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package com.iluwatar.reactor;
2+
3+
import java.io.IOException;
4+
import java.io.OutputStream;
5+
import java.io.PrintWriter;
6+
import java.net.InetAddress;
7+
import java.net.Socket;
8+
9+
public class AppClient {
10+
11+
public static void main(String[] args) {
12+
new LoggingClient("Client 1", 6666).start();
13+
}
14+
15+
16+
/*
17+
* A logging client that sends logging requests to logging server
18+
*/
19+
static class LoggingClient {
20+
21+
private int serverPort;
22+
private String clientName;
23+
24+
public LoggingClient(String clientName, int serverPort) {
25+
this.clientName = clientName;
26+
this.serverPort = serverPort;
27+
}
28+
29+
public void start() {
30+
Socket socket = null;
31+
try {
32+
socket = new Socket(InetAddress.getLocalHost(), serverPort);
33+
OutputStream outputStream = socket.getOutputStream();
34+
PrintWriter writer = new PrintWriter(outputStream);
35+
writeLogs(writer);
36+
} catch (IOException e) {
37+
e.printStackTrace();
38+
throw new RuntimeException(e);
39+
} finally {
40+
if (socket != null) {
41+
try {
42+
socket.close();
43+
} catch (IOException e) {
44+
e.printStackTrace();
45+
}
46+
}
47+
}
48+
}
49+
50+
private void writeLogs(PrintWriter writer) {
51+
for (int i = 0; i < 10; i++) {
52+
writer.println(clientName + " - Log request: " + i);
53+
try {
54+
Thread.sleep(1000);
55+
} catch (InterruptedException e) {
56+
e.printStackTrace();
57+
}
58+
writer.flush();
59+
}
60+
}
61+
}
62+
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package com.iluwatar.reactor;
2+
3+
import java.io.IOException;
4+
import java.net.InetSocketAddress;
5+
import java.nio.channels.SelectionKey;
6+
import java.nio.channels.Selector;
7+
import java.nio.channels.ServerSocketChannel;
8+
import java.nio.channels.SocketChannel;
9+
import java.util.Set;
10+
11+
public class NioReactor {
12+
13+
private int port;
14+
private Selector selector;
15+
private ServerSocketChannel serverSocketChannel;
16+
private NioChannelEventHandler nioEventhandler;
17+
18+
public NioReactor(int port, NioChannelEventHandler handler) {
19+
this.port = port;
20+
this.nioEventhandler = handler;
21+
}
22+
23+
24+
public void start() throws IOException {
25+
startReactor();
26+
requestLoop();
27+
}
28+
29+
private void startReactor() throws IOException {
30+
selector = Selector.open();
31+
serverSocketChannel = ServerSocketChannel.open();
32+
serverSocketChannel.socket().bind(new InetSocketAddress(port));
33+
serverSocketChannel.configureBlocking(false);
34+
SelectionKey acceptorKey = serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
35+
acceptorKey.attach(new Acceptor());
36+
System.out.println("Reactor started listening on port: " + port);
37+
}
38+
39+
private void requestLoop() throws IOException {
40+
while (true) {
41+
selector.select();
42+
Set<SelectionKey> keys = selector.selectedKeys();
43+
for (SelectionKey key : keys) {
44+
dispatchEvent(key);
45+
}
46+
keys.clear();
47+
}
48+
}
49+
50+
private void dispatchEvent(SelectionKey key) throws IOException {
51+
Object handler = key.attachment();
52+
if (handler != null) {
53+
((EventHandler)handler).handle();
54+
}
55+
}
56+
57+
interface EventHandler {
58+
void handle() throws IOException;
59+
}
60+
61+
private class Acceptor implements EventHandler {
62+
63+
public void handle() throws IOException {
64+
// non-blocking accept as acceptor will only be called when accept event is available
65+
SocketChannel clientChannel = serverSocketChannel.accept();
66+
if (clientChannel != null) {
67+
new ChannelHandler(clientChannel).handle();
68+
}
69+
System.out.println("Connection established with a client");
70+
}
71+
}
72+
73+
public static interface NioChannelEventHandler {
74+
void onReadable(SocketChannel channel);
75+
}
76+
77+
private class ChannelHandler implements EventHandler {
78+
79+
private SocketChannel clientChannel;
80+
private SelectionKey selectionKey;
81+
82+
public ChannelHandler(SocketChannel clientChannel) throws IOException {
83+
this.clientChannel = clientChannel;
84+
clientChannel.configureBlocking(false);
85+
selectionKey = clientChannel.register(selector, 0);
86+
selectionKey.attach(this);
87+
selectionKey.interestOps(SelectionKey.OP_READ);
88+
selector.wakeup();
89+
}
90+
91+
public void handle() throws IOException {
92+
// only read events are supported.
93+
nioEventhandler.onReadable(clientChannel);
94+
}
95+
}
96+
}

0 commit comments

Comments
 (0)