1. 思路
- 首先,我们通过一个时序图来看下如何创建一个NIO服务端并启动监听,接收多个客户端的连接,进行消息的异步读写。
public class NioServer
{
public static void main(String[] args)
{
ServerSocketChannel channel = null;
Selector selector = null;
try
{
InetSocketAddress address = new InetSocketAddress(8400);
channel = ServerSocketChannel.open();
channel.configureBlocking(false);
channel.socket().bind(address);
selector = Selector.open();
channel.register(selector, SelectionKey.OP_ACCEPT);
} catch (IOException ex)
{
System.out.println("Couldn't setup server socket");
System.out.println(ex.getMessage());
System.exit(1);
}
ListenerThread listener = new ListenerThread(selector);
listener.start();
}
}
class ListenerThread extends Thread
{
private Selector selector = null;
public ListenerThread(Selector selector)
{
this.selector = selector;
}
public void run()
{
while (true)
{
try
{
while (this.selector.select() > 0)
{
Set<SelectionKey> keys = this.selector.selectedKeys();
Iterator<SelectionKey> iterator = keys.iterator();
while (iterator.hasNext())
{
SelectionKey key = iterator.next();
if (key.isAcceptable())
{
System.out.println("Accepting connection!");
ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();
SocketChannel channel = serverChannel.accept();
channel.configureBlocking(false);
channel.register(this.selector, SelectionKey.OP_READ);
} else if (key.isReadable())
{
System.out.println("Accpting command!");
SocketChannel channel = (SocketChannel) key.channel();
ByteBuffer _buffer = ByteBuffer.allocate(256);
channel.read(_buffer);
_buffer.flip();
Charset charset = Charset.forName("UTF-8");
CharsetDecoder decoder = charset.newDecoder();
CharBuffer charBuffer = decoder.decode(_buffer);
System.out.println(charBuffer.toString());
channel.register(this.selector, SelectionKey.OP_WRITE);
} else if (key.isWritable())
{
System.out.println("Sending response!");
SocketChannel channel = (SocketChannel) key.channel();
channel.write(ByteBuffer.wrap(new String("Hello World\n").getBytes()));
channel.register(this.selector, SelectionKey.OP_READ);
}
iterator.remove();
}
}
} catch (IOException ex)
{
System.out.println("Error in poll loop");
System.out.println(ex.getMessage());
System.exit(1);
}
}
}
}
- 在window下,通过telnet 127.0.0.1 8400 即可测试程序的运行过程与结果。