Java NIO.2
Network socket
Network socket is an endpoint of a connection across a computer network.
Main types of Internet socket:
● Datagram sockets, which use User Datagram Protocol (UDP).
● Stream sockets, which use Transmission Control Protocol (TCP) or Stream Control Transmission Protocol (SCTP).
● Raw sockets, typically available in routers and other network equipment.
Java IO vs NIO
IO NIO
Stream-oriented Buffer-oriented
Blocking I/O Non-blocking I/O
Selectors
Channels
Java.IO - Stream-oriented
Data Source Program
Data Destination Program
001001001111001001001001011
001001001111001001001001011
Java.IO - Blocking I/O
Socket Thread
read data, block until ready
read data, block until ready
write data, block until ready
write data, block until ready
Java.IO — Work with data
// read from socketScanner sc = new Scanner(socket.getInputStream());String string = sc.nextLine();System.out.println("Received " + string);
// write to socketPrintWriter pw = new PrintWriter(socket.getOutputStream());pw.println("Hello");
Java.NIO — Buffer-oriented & Non-blocking I/O
Channel Buffer Thread
read data into buffer
fill data into buffer
check data in buffer
goto top
Java.NIO — Work with dataByteBuffer readBuffer = ByteBuffer.allocate(1024);// prepare to readreadBuffer.clear();SocketChannel channel = getChannel();channel.read(readBuffer);readBuffer.flip();// reading the buffer// ...............…
ByteBuffer writeBuffer = ByteBuffer.allocate(1024);// prepare to put datawriteBuffer.clear();// putting the data// ...............// prepare to writewriteBuffer.flip();channel.write(writeBuffer);
Java.NIO — Selector & Channels
Channel is a lightweight entity effeciently transporting data between sockets as a tube.
Selector is a manager allowing a single thread to monitor multiple input channels.
Java.IO - Classic IO server design
ServerSocket Thread
Connection Thread
Connection Thread
Connection Thread
Connection Thread
Java.NIO — NIO server design
Thread
Selector
Channel Channel Channel Channel
Java.NIO — NIO server designServerSocketChannel channel = ServerSocketChannel.open();channel.bind(new InetSocketAddress("localhost", 2222));channel.configureBlocking(false);
Selector selector = Selector.open();SelectionKey key = channel.register(selector, SelectionKey.OP_ACCEPT);
while (true) { if (selector.select() == 0) { Thread.sleep(1); continue; } Set<SelectionKey> selectedKeys = selector.selectedKeys(); Iterator<SelectionKey> keyIterator = selectedKeys.iterator(); while (keyIterator.hasNext()) { SelectionKey selectionKey = keyIterator.next(); if (selectionKey.isAcceptable()) { // a connection was accepted by a ServerSocketChannel. } else if (selectionKey.isConnectable()) { // a connection was established with a remote. } else if (selectionKey.isReadable()) { // a channel is ready for reading } else if (selectionKey.isWritable()) { // a channel is ready for writing } keyIterator.remove(); }}
Java NIO.1 vs NIO.2
NIO.1 NIO.2Selector AsynchronousChannelGroup
ServerSocketChannel AsynchronousServerSocketChannel
SocketChannel AsynchronousSocketChannel
SelectionKey CompletionHandler
Java.NIO.2 — Reading
ByteBuffer readBuffer = ByteBuffer.allocate(1024);// prepare to readreadBuffer.clear();
AsynchronousSocketChannel channel = getChannel2();channel.read(readBuffer, null, new CompletionHandler<Integer, Object>() { @Override public void completed(Integer result, Object attachment) { // buffer is ready for read } @Override public void failed(Throwable exc, Object attachment) { exc.printStackTrace(); }});
Java.NIO.2 — WritingByteBuffer writeBuffer = ByteBuffer.allocate(1024);// prepare to put datawriteBuffer.clear();// putting data// ...............// prepare to writewriteBuffer.flip();
AsynchronousSocketChannel channel = getChannel2();channel.write(writeBuffer, null, new CompletionHandler<Integer, Object>() { @Override public void completed(Integer result, Object attachment) { // writing has been completed } @Override public void failed(Throwable exc, Object attachment) { exc.printStackTrace(); }});
Java.NIO — NIO.1 server designServerSocketChannel channel = ServerSocketChannel.open();channel.bind(new InetSocketAddress("localhost", 2222));channel.configureBlocking(false);
Selector selector = Selector.open();SelectionKey key = channel.register(selector, SelectionKey.OP_ACCEPT);
while (true) { if (selector.select() == 0) { Thread.sleep(1); continue; } Set<SelectionKey> selectedKeys = selector.selectedKeys(); Iterator<SelectionKey> keyIterator = selectedKeys.iterator(); while (keyIterator.hasNext()) { SelectionKey selectionKey = keyIterator.next(); if (selectionKey.isAcceptable()) { // a connection was accepted by a ServerSocketChannel. } else if (selectionKey.isConnectable()) { // a connection was established with a remote. } else if (selectionKey.isReadable()) { // a channel is ready for reading } else if (selectionKey.isWritable()) { // a channel is ready for writing } keyIterator.remove(); }}
Java.NIO — NIO.2 server designAsynchronousChannelGroup group = AsynchronousChannelGroup.withThreadPool(newFixedThreadPool(10));
AsynchronousServerSocketChannel channel = open(group);channel.bind(new InetSocketAddress("localhost", 2222));channel.accept(null, toHandler((client, attach) -> { ByteBuffer readBuffer = ByteBuffer.allocate(1024); ByteBuffer writeBuffer = ByteBuffer.allocate(1024); client.read(readBuffer, null, toHandler((result, attachment) -> { // buffer is ready for read })); client.write(writeBuffer, null, toHandler((result, attachment) -> { // writing has been completed }));}));
public class NetworkServer { AsynchronousServerSocketChannel channel; CompletionHandler<AsynchronousSocketChannel, Void> handler; public NetworkServer(SocketAddress address) throws IOException { AsynchronousChannelGroup group = withFixedThreadPool(10, Thread::new); handler = toHandler((channel, attach) -> processAccept(channel)); channel = AsynchronousServerSocketChannel.open(group); channel.bind(address); channel.accept(null, toHandler((clientChannel, attach) -> processAccept(clientChannel))); }
private void processAccept(AsynchronousSocketChannel clientChannel) { NetworkClient networkClient = new NetworkClient(clientChannel, message -> out.println("Server: received: " + message)); networkClient.write("Hello! I'm NIO.2 server!\n"); channel.accept(null, handler); }
public void stop() throws IOException { channel.close(); }}
Java NIO.2 — Basic implementation of server
public class NetworkClient { AtomicBoolean isWriting = new AtomicBoolean(); Deque<String> toWrite = new ConcurrentLinkedDeque<>(); Consumer<String> readFunction; CompletionHandler<Integer, ByteBuffer> readHandler = toHandler((byteCount, buffer) -> finishRead(byteCount)); CompletionHandler<Integer, ByteBuffer> writeHandler = toHandler((byteCount, buffer) -> finishWrite()); ByteBuffer rb = allocateDirect(1024); ByteBuffer wb = allocateDirect(1024); AsynchronousSocketChannel channel; public NetworkClient(AsynchronousSocketChannel channel, Consumer<String> readFunction) { this.channel = channel; this.readFunction = readFunction; readNext(); } private void finishRead(Integer byteCount) { if(byteCount.equals(-1)) return; readFunction.accept(NUtils.read(rb)); readNext(); } private void finishWrite() { if (isWriting.compareAndSet(true, false)) writeNext(); } public void write(String message) { toWrite.add(message); if(isWriting.compareAndSet(false, true)) writeNext(); } private void writeNext() { if(toWrite.isEmpty()) return; NUtils.write(wb, toWrite); channel.write(wb, wb, writeHandler); } private void readNext() { channel.read(rb, rb, readHandler); }}
Java NIO.2 — Basic implementation of server
new Thread(run(() -> { final NetworkServer server = new NetworkServer(new InetSocketAddress(3333)); ConcurrentUtils.wait(counter); server.stop();})).start();
ThreadUtils.sleep(1000);
for (int i = 0, length = CLIENT_COUNT; i < length; i++) { new Thread(run(() -> { Socket socket = new Socket(); socket.connect(new InetSocketAddress(3333)); writeLine(socket, "Hello! I'm client " + currentThread().getName()); System.out.println("Client: received: " + readLine(socket)); synchronized (counter) { if (counter.decrementAndGet() == 0) { ConcurrentUtils.notifyAll(counter); } else { ConcurrentUtils.wait(counter); } } socket.close(); })).start();}
Java NIO.2 — Test
Java NIO.2 — Test
Server: received: Hello! I'm client Thread-16Server: received: Hello! I'm client Thread-19Server: received: Hello! I'm client Thread-11Server: received: Hello! I'm client Thread-20Server: received: Hello! I'm client Thread-15Server: received: Hello! I'm client Thread-18Server: received: Hello! I'm client Thread-12Server: received: Hello! I'm client Thread-14Server: received: Hello! I'm client Thread-13Server: received: Hello! I'm client Thread-17Client: received: Hello! I'm NIO.2 server!Client: received: Hello! I'm NIO.2 server!Client: received: Hello! I'm NIO.2 server!Client: received: Hello! I'm NIO.2 server!Client: received: Hello! I'm NIO.2 server!Client: received: Hello! I'm NIO.2 server!Client: received: Hello! I'm NIO.2 server!Client: received: Hello! I'm NIO.2 server!Client: received: Hello! I'm NIO.2 server!Client: received: Hello! I'm NIO.2 server!
All thanks
Repository with my code examples:https://bitbucket.org/JavaSabr/publictest
Top Related