Java NIO Example

Simple Echo Server - Binds to both TCP and UDP ports 5050, and 5051 and will echo all data received to all other connections. It will treat all data as a String so use "telnet localhost 5050" or if you have netcat you can use "nc -u localhost 5050" to send udp packets to the server.

Solution:
/*
Simple Echo Server
Binds to both TCP and UDP ports 5050, and 5051
and will echo all data received to all other
connections. It will treat all data as a String
so use "telnet localhost 5050" or if you have
netcat you can use "nc -u localhost 5050" to
send udp packets to the server.
*/
package nioexample;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Queue;
import java.util.concurrent.TimeUnit;

public class NioExample implements Runnable{
   
    final private Thread nioThread;
    final private Selector selector;
   
    final private Queue<Runnable> runnableQueue = new LinkedList<Runnable>();
   
    final private List<Attachment> attachments = new ArrayList<Attachment>();
   
    public NioExample() throws IOException{
        selector = Selector.open();
        nioThread = new Thread(this);
        nioThread.setName("NioExample");
    }
   
    public void start(){
        if(!nioThread.isAlive()) nioThread.start();
    }
   
    @Override
    public void run() {
        ByteBuffer reusableBuffer = ByteBuffer.allocate(0x4000);
        while(selector.isOpen()){
            if(!runnableQueue.isEmpty()) handleQueue();
            try{
                handleSelect(reusableBuffer);
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    }
   
    public void runOnNioThread(Runnable runnable){
        synchronized(runnableQueue){
            runnableQueue.add(runnable);
            selector.wakeup();
        }
    }
   
    private void handleQueue(){
        synchronized(runnableQueue){
            Runnable runnable;
            while((runnable = runnableQueue.poll()) != null) runnable.run();
        }
    }
   
    private void handleSelect(ByteBuffer buffer) throws IOException{
        int totalKeys = selector.select();
        Iterator<SelectionKey> selectedKeys = selector.selectedKeys().iterator();
        while(selectedKeys.hasNext()){
            buffer.clear();
            SelectionKey key = selectedKeys.next();
            SelectableChannel channel = key.channel();
            Attachment attachment = (Attachment)key.attachment();
            try{
                if(key.isValid()){
                    if(key.isReadable()){
                        if(channel instanceof DatagramChannel){
                            DatagramChannel dChannel = (DatagramChannel)channel;
                            SocketAddress remote = dChannel.receive(buffer);
                            if(remote != null){
                                buffer.flip();
                                attachment.onReceiveData(buffer, remote);
                            }else{
                               
                            }
                        }else if(channel instanceof SocketChannel){
                            SocketChannel sChannel = (SocketChannel)channel;
                            int bytesRead = sChannel.read(buffer);
                            buffer.flip();
                            if(bytesRead == -1){
                                key.cancel();
                                attachment.onClosed();
                            }else{
                                attachment.onReceiveData(buffer);
                            }
                        }
                    }else if(key.isAcceptable()){
                        ServerSocketChannel ssChannel = (ServerSocketChannel)channel;
                        SocketChannel sChannel = ssChannel.accept();
                        sChannel.configureBlocking(false);
                        Attachment sAttachment = new Attachment();
                        sAttachment.channel = sChannel;
                        sChannel.register(selector, SelectionKey.OP_READ, sAttachment);
                        sAttachment.onStart();
                    }
                }else{ //INVALID KEY
                   
                }
            }catch(Exception e){
                key.cancel();
                attachment.onClosed();
                e.printStackTrace();
            }finally{
                selectedKeys.remove();
            }
        }
    }
   
    public Attachment createServerSocket(final SocketAddress address){
        final Attachment attachment = new Attachment();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                try {
                    ServerSocketChannel ssChannel = ServerSocketChannel.open();
                    attachment.channel = ssChannel;
                    ssChannel.configureBlocking(false);
                    ssChannel.socket().bind(address);
                    ssChannel.register(selector, SelectionKey.OP_ACCEPT, attachment);
                    attachment.onStart();
                } catch (IOException e) {
                    attachment.onClosed();
                    e.printStackTrace();
                }
            }
        };
        runOnNioThread(runnable);
        return attachment;
    }
   
    public Attachment createDatagramSocket(final SocketAddress address){
        final Attachment attachment = new Attachment();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                try {
                    DatagramChannel dChannel = DatagramChannel.open();
                    attachment.channel = dChannel;
                    dChannel.configureBlocking(false);
                    dChannel.socket().bind(address);
                    dChannel.register(selector, SelectionKey.OP_READ, attachment);
                    attachment.onStart();
                } catch (IOException e) {
                    attachment.onClosed();
                    e.printStackTrace();
                }
            }
        };
        runOnNioThread(runnable);
        return attachment;
    }
   
    public void sendToAll(ByteBuffer buffer){
        for(Attachment a:attachments){
            try {
                if(a.channel instanceof SocketChannel){
                    a.send(buffer);
                    buffer.flip();
                }else if(a.channel instanceof DatagramChannel){
                    a.sendToAll(buffer);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
   
    public static void main(String[] args) throws IOException {
        NioExample nio = new NioExample();
        nio.start();
        nio.createServerSocket(new InetSocketAddress(5050));
        nio.createServerSocket(new InetSocketAddress(5051));
        nio.createDatagramSocket(new InetSocketAddress(5050));
        nio.createDatagramSocket(new InetSocketAddress(5051));
    }
   
    public class Attachment{
        SelectableChannel channel;
        Map<SocketAddress, Long> remoteAddresses = new HashMap<SocketAddress, Long>();
        void onStart(){
            attachments.add(this);
            System.out.println("Started Listening " + channel);
        }
        void onReceiveData(ByteBuffer buffer){
            System.out.printf("Received TCP(%s): %s\n",
                    ((SocketChannel)channel).socket().getRemoteSocketAddress(),
                    new String(buffer.array(), buffer.position(), buffer.limit()));
            NioExample.this.sendToAll(buffer);
        }
        void onReceiveData(ByteBuffer buffer, SocketAddress remote){
            remoteAddresses.put(remote, System.currentTimeMillis());
            System.out.printf("Received UDP(%s): %s\n",
                    remote, new String(buffer.array(), buffer.position(), buffer.limit()));
            NioExample.this.sendToAll(buffer);
        }
        void onClosed(){
            attachments.remove(this);
            System.out.println("Closed " + channel);
        }
       
        public synchronized void send(ByteBuffer data) throws IOException{
            SocketChannel sChannel = (SocketChannel)channel;
            sChannel.write(data);
        }
       
        public synchronized void sendTo(ByteBuffer data, SocketAddress remote) throws IOException{
            if((System.currentTimeMillis() - remoteAddresses.get(remote)) > (TimeUnit.MINUTES.toMillis(5))){
                remoteAddresses.remove(remote);
                System.out.println("Deleted Entry " + remote);
                return;
            }
            DatagramChannel dChannel = (DatagramChannel)channel;
            dChannel.send(data, remote);
        }
       
        public void sendToAll(ByteBuffer data) throws IOException{
            Iterator<SocketAddress> addresses = remoteAddresses.keySet().iterator();
            while(addresses.hasNext()){
                sendTo(data, addresses.next());
                data.flip();
            }
        }
    }
}


Learn More :

Learn More Multiple Choice Question :