Netty核心功能——传输 (Transport)
Netty 为它所有的传输实现提供了一个通用 API,这使得这种转换比直接使用 JDK 所能够达到的简单得多。所产生的代码不会被实现的细节所污染,我们也不需要在整个代码库上进行广泛的重构。简而言之,我们可以将时间花在其他更有成效的事情上。
从一个例子开始
先来比较一下不使用netty以及使用netty所写出来的nio程序对比:
//只用 JDK API 来实现 NIO
public class PlainNioServer {
public void serve(int port) throws IOException {
ServerSocketChannel serverChannel = ServerSocketChannel.open();
serverChannel.configureBlocking(false);
ServerSocket ss = serverChannel.socket();
InetSocketAddress address = new InetSocketAddress(port);
ss.bind(address); //1、绑定服务器到制定端口
Selector selector = Selector.open(); //2、打开 selector 处理 channel
serverChannel.register(selector, SelectionKey.OP_ACCEPT); //3、将ServerSocket 注册到Selector以接受连接
final ByteBuffer msg = ByteBuffer.wrap("Hi!\r\n".getBytes());
for (;;) {
try {
selector.select();//4、等待需要处理的新事件;阻塞将一直持续到下一个传入事件
} catch (IOException ex) {
ex.printStackTrace();
// handle exception
break;
}
Set<SelectionKey> readyKeys = selector.selectedKeys(); //5、获取所有接收事件的SelectionKey实例
Iterator<SelectionKey> iterator = readyKeys.iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
iterator.remove();
try {
if (key.isAcceptable()) { //6、检查事件是否是一个新的已经就绪可以被接受的连接
ServerSocketChannel server =
(ServerSocketChannel)key.channel();
SocketChannel client = server.accept();
client.configureBlocking(false);
client.register(selector, SelectionKey.OP_WRITE |
SelectionKey.OP_READ, msg.duplicate()); //7、接受客户端,并将它注册到选择器
System.out.println(
"Accepted connection from " + client);
}
if (key.isWritable()) { //8、检查套接字是否已经准备好写数据
SocketChannel client =
(SocketChannel)key.channel();
ByteBuffer buffer =
(ByteBuffer)key.attachment();
while (buffer.hasRemaining()) {
if (client.write(buffer) == 0) { //9、将数据写到已连接的客户端
break;
}
}
client.close(); //10、关闭连接
}