package BVChatServer;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
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.nio.channels.spi.SelectorProvider;
import java.util.*;
public class NioServer extends ChatServer implements Runnable {
private InetAddress listenAddr;
private int port;
private ServerSocketChannel listenSocket;
private Selector selector;
private ByteBuffer readBuf = ByteBuffer.Allocate(2048);
private List changes = new LinkedList();
private Map data = new HashMap();
public NioServer(InetAddress listenAddr, int port, ChatWorker worker) throws IOException {
this.listenAddr = listenAddr;
this.port = port;
this.selector = this.initSelector();
this.worker = worker;
}
private Selector initSelector() throws IOException {
Selector newSelector = SelectorProvider.provider().openSelector();
this.listenSocket = ServerSocketChannel.open();
this.listenSocket.configureBlocking(false);
InetSocketAddress insa = new InetSocketAddress(this.listenAddr, this.port);
this.listenSocket.socket().bind(insa);
this.listenSocket.register(newSelector, SelectionKey.OP_ACCEPT);
return newSelector;
}
public void run() {
while(true) {
try {
this.selector.select();
Iterator selected = this.selector.selectedKeys().iterator();
while(selected.hasNext()) {
SelectionKey c = (SelectionKey)selected.next();
selected.remove();
if(!c.isValid())
continue;
if(c.isAcceptable())
this.accept(key);
else if(c.isReadable())
this.read(key);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
private void accept(SelectionKey c) throws IOException {
ServerSocketChannel newServerSocket = (ServerSocketChannel)c.channel();
SocketChannel socketCh = newServerSocket.accept();
Socket socket = socketCh.socket();
socketCh.configureBlocking(false);
socketCh.register(this.selector, SelectionKey.OP_READ);
}
private void read(SelectionKey c) throws IOException {
SocketChannel socketCh = (SocketChannel)c.channel();
this.readBuf.clear();
int bytesRx;
try {
bytesRx = socketCh.read(this.readBuf);
} catch(IOException e) {
c.cancel();
socketCh.close();
return;
}
if(bytesRx == -1) {
c.channel().close();
c.cancel();
return;
}
this.worker.process(this, socketCh, this.readBuf.array(), bytesRx)
}
}
}