11package com .iluwatar .reactor ;
22
33import java .io .IOException ;
4- import java .net . InetSocketAddress ;
4+ import java .nio . channels . SelectableChannel ;
55import java .nio .channels .SelectionKey ;
66import java .nio .channels .Selector ;
77import java .nio .channels .ServerSocketChannel ;
88import java .nio .channels .SocketChannel ;
9+ import java .util .List ;
910import java .util .Set ;
11+ import java .util .concurrent .CopyOnWriteArrayList ;
1012
13+ /*
14+ * Abstractions
15+ * ---------------
16+ *
17+ * 1 - Dispatcher
18+ * 2 - Synchronous Event De-multiplexer
19+ * 3 - Event
20+ * 4 - Event Handler & concrete event handler (application business logic)
21+ * 5 - Selector
22+ */
1123public class NioReactor {
1224
13- private int port ;
1425 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 ;
26+ private Acceptor acceptor ;
27+ private List < NioChannelEventHandler > eventHandlers = new CopyOnWriteArrayList <>() ;
28+
29+ public NioReactor () throws IOException {
30+ this .acceptor = new Acceptor () ;
31+ this .selector = Selector . open () ;
2132 }
2233
34+ public NioReactor registerChannel (SelectableChannel channel ) throws IOException {
35+ SelectionKey key = channel .register (selector , SelectionKey .OP_ACCEPT );
36+ key .attach (acceptor );
37+ return this ;
38+ }
39+
40+ public void registerHandler (NioChannelEventHandler handler ) {
41+ eventHandlers .add (handler );
42+ }
2343
2444 public void start () throws IOException {
25- startReactor ();
26- requestLoop ();
45+ new Thread ( new Runnable () {
46+ @ Override
47+ public void run () {
48+ try {
49+ System .out .println ("Reactor started, waiting for events..." );
50+ eventLoop ();
51+ } catch (IOException e ) {
52+ e .printStackTrace ();
53+ }
54+ }
55+ }).start ();
2756 }
2857
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 {
58+ private void eventLoop () throws IOException {
4059 while (true ) {
41- selector .select ();
60+ selector .select (1000 );
4261 Set <SelectionKey > keys = selector .selectedKeys ();
4362 for (SelectionKey key : keys ) {
4463 dispatchEvent (key );
@@ -50,21 +69,21 @@ private void requestLoop() throws IOException {
5069 private void dispatchEvent (SelectionKey key ) throws IOException {
5170 Object handler = key .attachment ();
5271 if (handler != null ) {
53- ((EventHandler )handler ).handle ();
72+ ((EventHandler )handler ).handle (key . channel () );
5473 }
5574 }
5675
5776 interface EventHandler {
58- void handle () throws IOException ;
77+ void handle (SelectableChannel channel ) throws IOException ;
5978 }
6079
6180 private class Acceptor implements EventHandler {
6281
63- public void handle () throws IOException {
82+ public void handle (SelectableChannel channel ) throws IOException {
6483 // non-blocking accept as acceptor will only be called when accept event is available
65- SocketChannel clientChannel = serverSocketChannel .accept ();
84+ SocketChannel clientChannel = (( ServerSocketChannel ) channel ) .accept ();
6685 if (clientChannel != null ) {
67- new ChannelHandler (clientChannel ).handle ();
86+ new ChannelHandler (clientChannel ).handle (clientChannel );
6887 }
6988 System .out .println ("Connection established with a client" );
7089 }
@@ -88,9 +107,11 @@ public ChannelHandler(SocketChannel clientChannel) throws IOException {
88107 selector .wakeup ();
89108 }
90109
91- public void handle () throws IOException {
110+ public void handle (SelectableChannel channel ) throws IOException {
92111 // only read events are supported.
93- nioEventhandler .onReadable (clientChannel );
112+ for (NioChannelEventHandler eventHandler : eventHandlers ) {
113+ eventHandler .onReadable (clientChannel );
114+ }
94115 }
95116 }
96117}
0 commit comments