Presentation is loading. Please wait.

Presentation is loading. Please wait.

System Programming Practical session 12 Reactor.

Similar presentations


Presentation on theme: "System Programming Practical session 12 Reactor."— Presentation transcript:

1 System Programming Practical session 12 Reactor

2 Thread-Per-Client downsides
Each thread waste resources. Blocking I/O. Vulnerability to denial of service attack. The Reactor design pattern solve these problems. One thread deals with communication. Fixed number of threads deal with work. communication and work layers are separate and asynchronous. Non-blocking I/O.

3 Non-Blocking I/O Server ConnectionAcceptor ServerSocketChannel
key Selector ConnectionAcceptor ServerSocketChannel SocketChannel ConnectionHandler SocketChannel SocketChannel ProtocolTask SocketChannel

4 Channels Channels wrap sockets, and allow non-blocking I/O.
read(), write() , accept() can be non blocking. Setting up a non-blocking ServerSocketChannel listening on a specific port. int port = 9999; ServerSocketChannel ssChannel = serverSocketChannel.open(); ssChannel.configureBlocking(false); ssChannel.socket().bind(new InetSocketAddress(port));

5 Buffers ByteBuffer are buffers that hold bytes.
Channels know how to read and write to buffers. Creating a Buffer final int NUM_OF_BYTES = 1024; ByteBuffer buf = ByteBuffer.allocate(NUM_OF_BYTES); From Channel to Buffer and back numBytesRead = _socketChannel.read(buf1); numBytesWritten = _socketChannel.write(buf2); Return –1 if channel is closed. Update position marker of the buffer.

6 Selector The selector monitors the channels for new events (new data arrived, new connection). A Selector is registered to each channel with an attachment to handle the event. An appropriate attachment is invoked for each new event. Selector selector = Selector.open(); Object anAttachment = new Object(); socketChannel.register(selector, SelectionKey.OP_READ, anAttachmemt);

7 select() Method selector.select();
Blocks until at least one of the channels is ready for the registered event. A list of SelectionKeys is returned. Each Selectionkey is associated with one event, and holds the attachment registered with the event.

8 Reactor Actors Reactor – The main class. Creates ServerSocket channel
Registers the Selector For each event, invokes the appropriate attachment ConnectionAcceptor ConnectionHandler

9 Reactor Actors ConnectionAcceptor accept() Creates SocketChanel.
Register the Selector. Creates ConnectionHandler.

10 Reactor Actors ConnectionHandler Read() Reads new data from channel.
Adds ProtoclTask for yet unprocessed input data to a fixed thread pool. Write() Receives output data from ProtocolTask. Writes the data to the channel.

11 Reactor Actors ProtocolTask
Passes unprocessed input data to message tokenizer. Processes each complete message. Passes output data to ConnectionHandler.

12 Execution example ssChannel selector executor public class Reactor{
... selector ssChannel ServerSocketChannel ssChannel = ServerSocketChannel.open(); ssChannel.configureBlocking( false); ssChannel.socket().bind(new InetSocketAddress(port)); Selector selector = Selector.open(); ssChannel.register(selector, SelectionKey.OP_ACCEPT, connectionAcceptor);  ExecutorService executor =  Executors.newFixedThreadPool( _poolSize); executor

13 while (_shouldRun && selector.isOpen()) {
try { selector.select(); } catch (IOException e) {…} Iterator it = selector.selectedKeys().iterator(); while (it.hasNext()) { SelectionKey selKey = (SelectionKey) it.next(); it.remove(); if (selKey.isValid() && selKey.isAcceptable()) { ConnectionAcceptor acceptor = (ConnectionAcceptor) selKey.attachment(); acceptor.accept(); } catch (IOException e) {…) if (selKey.isValid() && selKey.isReadable()) { //Handle reading… } if (selKey.isValid() && selKey.isWritable()) { //Handle writing… } }

14 ssChannel selector sChannel sChannel sChannel
public class ConnectionAcceptor { public void accept() { SocketChannel sChannel = _ssChannel.accept(); if (sChannel != null) { sChannel.configureBlocking(false); SelectionKey key =sChannel.register( _data.getSelector(), 0); ConnectionHandler handler = ConnectionHandler.create(sChannel, _data, key); handler.switchToReadOnlyMode();} } Client connection request selector ssChannel sChannel sChannel sChannel

15 selector ssChannel “Don’t worry” sChannel sChannel sChannel

16 while (_shouldRun && selector.isOpen()) {
try { selector.select(); } catch (IOException e) {…} Iterator it = selector.selectedKeys().iterator(); while (it.hasNext()) { SelectionKey selKey = (SelectionKey) it.next(); it.remove(); if (selKey.isValid() && selKey.isAcceptable()) { … } if (selKey.isValid() && selKey.isReadable()) { ConnectionHandler handler = (ConnectionHandler) selKey.attachment(); handler.read(); } if (selKey.isValid() && selKey.isWritable()) { //Handle writing… }

17 ssChannel selector “Don’t worry” sChannel sChannel sChannel
public class ConnectionHandler {… public void read() { ByteBuffer buf = ByteBuffer.allocate(BUFFER_SIZE); int numBytesRead = 0; try { numBytesRead =sChannel.read(buf); } catch (IOException e) { numBytesRead = -1; } if (numBytesRead == -1) { closeConnection(); _protocol.connectionTerminated(); return; } buf.flip(); _task.addBytes(buf); _data.getExecutor().execute(_task); selector ssChannel “Don’t worry” sChannel sChannel sChannel

18 _buffers public class ProtocolTask implements Runnable {
private final Vector<ByteBuffer> _buffers = new Vector<ByteBuffer>(); public synchronized void run() { synchronized (_buffers) { while(_buffers.size() > 0) { ByteBuffer buf = _buffers.remove(0); this._tokenizer.addBytes(buf); } } while (_tokenizer.hasMessage()) { public void addBytes(ByteBuffer b) { _buffers.add(b); _buffers

19 _tokenizer “Don’t worry” _buffers D o n ’ t w o r r y
public class ProtocolTask implements Runnable { private final Vector<ByteBuffer> _buffers = new Vector<ByteBuffer>(); public synchronized void run() { synchronized (_buffers) { while(_buffers.size() > 0) { ByteBuffer buf = _buffers.remove(0); this._tokenizer.addBytes(buf); } } while (_tokenizer.hasMessage()) { public void addBytes(ByteBuffer b) { _buffers.add(b); _tokenizer “Don’t worry” _buffers D o n ’ t w o r r y

20 ssChannel selector “be happy\n” sChannel sChannel sChannel
public class ConnectionHandler {… public void read() { ByteBuffer buf = ByteBuffer.allocate(BUFFER_SIZE); int numBytesRead = 0; try { numBytesRead =sChannel.read(buf); } catch (IOException e) { numBytesRead = -1; } if (numBytesRead == -1) { closeConnection(); _protocol.connectionTerminated(); return; } buf.flip(); _task.addBytes(buf); _data.getExecutor().execute(_task); selector ssChannel “be happy\n” sChannel sChannel sChannel

21 “Don’t worry be happy\n”
public class ProtocolTask implements Runnable {… public synchronized void run() { synchronized (_buffers) { while(_buffers.size() > 0) { ByteBuffer buf = _buffers.remove(0); this._tokenizer.addBytes(buf); } } while (_tokenizer.hasMessage()) { String msg = _tokenizer.nextMessage(); String response = this._protocol.processMessage(msg); if (response != null) { try { ByteBuffer bytes = _tokenizer.getBytesForMessage(response); this._handler.addOutData(bytes); } catch (CharacterCodingException e) { … } } } } public void addBytes(ByteBuffer b) { synchronized (_buffers) { _buffers.add(b); } } _tokenizer “Don’t worry be happy\n” response “Your message “Don’t worry be happy” received”

22 public class ConnectionHandler{
public synchronized void addOutData(ByteBuffer buf) { _outData.add(buf); switchToReadWriteMode(); } public void switchToReadWriteMode() { _skey.interestOps(SelectionKey.OP_READ | SelectionKey.OP_WRITE); _data.getSelector().wakeup();

23 selector ssChannel sChannel sChannel sChannel

24 while (_shouldRun && selector.isOpen()) {
try { selector.select(); } catch (IOException e) {…} Iterator it = selector.selectedKeys().iterator(); while (it.hasNext()) { SelectionKey selKey = (SelectionKey) it.next(); it.remove(); if (selKey.isValid() && selKey.isAcceptable()) { … } if (selKey.isValid() && selKey.isReadable()){…} if (selKey.isValid() && selKey.isWritable()){ ConnectionHandler handler = (ConnectionHandler) selKey.attachment(); handler.write(); }

25 ssChannel selector sChannel sChannel sChannel
public synchronized void write() { if (_outData.size() == 0) { switchToReadOnlyMode(); return; } ByteBuffer buf = _outData.remove(0); if (buf.remaining() != 0) { try { _sChannel.write(buf); } catch (IOException e) {…} _outData.add(0, buf); } } if (_protocol.shouldClose()) { switchToWriteOnlyMode(); if (buf.remaining() == 0) { closeConnection(); ssChannel selector “Your message “Don’t worry be happy” received” sChannel sChannel sChannel

26 ssChannel selector sChannel sChannel
public synchronized void write() { if (_outData.size() == 0) { switchToReadOnlyMode(); return; } ByteBuffer buf = _outData.remove(0); if (buf.remaining() != 0) { try { _sChannel.write(buf); } catch (IOException e) {…} _outData.add(0, buf); } } if (_protocol.shouldClose()) { switchToWriteOnlyMode(); if (buf.remaining() == 0) { closeConnection(); ssChannel selector sChannel sChannel


Download ppt "System Programming Practical session 12 Reactor."

Similar presentations


Ads by Google