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();
}
}
}
}
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 :
telnet localhost 5050
5050
TCP
UDP
If the answers is incorrect or not given, you can answer the above question in the comment box. If the answers is incorrect or not given, you can answer the above question in the comment box.