Complete Example
To practice the knowledge we have learned in the previous sections, let’s see a complete client-server example
- We’ll build an echo server and an echo client.
- In this kind of setup, the client connects to the server and starts sending messages to it.
- The server echoes messages sent by each client.
When the server encounters a specific message, such as the end, it interprets it as the end of the communication and closes the connection with the client
Create a server: NIOServer.java
Java
//Java Program to test //echo server using NIO Selector import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.util.Iterator; import java.util.Set; //Driver class for NIOServer public class NIOServer { //Main method public static void main(String[] args) throws IOException { // Create a new Selector Selector selector = Selector.open(); // Create a ServerSocketChannel, bind it, and configure it as non-blocking ServerSocketChannel serverChannel = ServerSocketChannel.open(); serverChannel.bind( new InetSocketAddress( "localhost" , 5454 )); serverChannel.configureBlocking( false ); // Register the server socket channel with the Selector for accepting connections serverChannel.register(selector, SelectionKey.OP_ACCEPT); ByteBuffer buffer = ByteBuffer.allocate( 256 ); System.out.println( "Server started and listening on port 5454..." ); while ( true ) { // Select ready channels using the Selector selector.select(); // Get the set of selected keys Set<SelectionKey> selectedKeys = selector.selectedKeys(); Iterator<SelectionKey> keyIterator = selectedKeys.iterator(); while (keyIterator.hasNext()) { SelectionKey key = keyIterator.next(); if (key.isAcceptable()) { // Accept a new client connection ServerSocketChannel server = (ServerSocketChannel) key.channel(); SocketChannel clientChannel = server.accept(); clientChannel.configureBlocking( false ); // Register the client channel with the Selector for reading clientChannel.register(selector, SelectionKey.OP_READ); } if (key.isReadable()) { // Read data from the client SocketChannel client = (SocketChannel) key.channel(); buffer.clear(); int bytesRead = client.read(buffer); if (bytesRead == - 1 ) { // Client closed the connection key.cancel(); client.close(); continue ; } buffer.flip(); String receivedMessage = new String(buffer.array(), 0 , bytesRead); // Process the received message (e.g., echo it back to the client) System.out.println( "Received: " + receivedMessage); // Prepare the buffer for writing and echo the received message back to the client buffer.rewind(); client.write(buffer); } // Remove the processed key from the set keyIterator.remove(); } } } } |
Output of NIO Server:
Explanation
- The code is a Java NIO implementation of an echo server.
- It uses a Selector for efficient I/O handling.
- Listens on port 5454, accepts connections, and echoes received data.
- Non-blocking I/O allows handling multiple connections simultaneously.
- The server loop monitors events on registered channels.
- Accepted connections are registered for reading, and data is echoed back to clients.
Create a client: NIOClient.java
In this example we will create a NIOClient, using SocketChannel.
Java
//Java Program to create a //echo client using NIO Selector import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; //Driver class for NIOClient public class NIOClient { //Main method public static void main(String[] args) throws IOException { // Create a socket channel and connect to the server SocketChannel clientChannel = SocketChannel.open(); clientChannel.connect( new InetSocketAddress( "localhost" , 5454 )); ByteBuffer buffer = ByteBuffer.allocate( 256 ); String message = "Hello, NIO Server!" ; // Message to send to the server buffer.clear(); buffer.put(message.getBytes()); buffer.flip(); // Send the message to the server while (buffer.hasRemaining()) { clientChannel.write(buffer); } buffer.clear(); // Read the server's response clientChannel.read(buffer); buffer.flip(); // Convert the response to a String and print it String response = new String(buffer.array(), 0 , buffer.limit()); System.out.println( "Server Response: " + response); clientChannel.close(); } } |
Output of NIO Client:
Explanation of the above program:
- Creates a
SocketChannel
and connects to a server at localhost on port 5454. - Prepares a message (“Hello, NIO Server!”) and sends it to the server.
- Reads the server’s response into a buffer and converts it to a String.
- Prints the server’s response.
- Closes the client channel after communication.
java.nio.channels.Selector Class in Java
A selector is a tool that helps you keep an eye on one or more NIO channels and figure out when they’re ready to transfer data. In Java NIO, the Selector is a key player that looks at multiple Java NIO Channel instances and figures out which ones are good to go for actions like reading or writing.
This allows a single thread to handle many channels, making it easy to manage multiple network connections.