-
使用 JDK 的 NIO 实现异步的服务端,大体包括 创建 Channel=>绑定端口=>注册监听=>处理连接建立事件=>注册读写=>处理读写
public class MyPlainNioServer { public void serve(int port) throws IOException { ServerSocketChannel serverChannel = ServerSocketChannel.open(); serverChannel.configureBlocking(false); ServerSocket ssocket = serverChannel.socket(); InetSocketAddress address = new InetSocketAddress(port); ssocket.bind(address); Selector selector = Selector.open(); // 将 Channel 注册到 Selector serverChannel.register(selector, SelectionKey.OP_ACCEPT); final ByteBuffer msg = ByteBuffer.wrap("Hi!".getBytes()); for(;;) { try { // 等待需要处理的新事件;阻塞将一直持续到下一个传入事件 selector.select(); } catch (IOException ex) { ex.printStackTrace(); break; } // 获取所有接收事件的 SelectionKey 实例 Set<SelectionKey> readyKeys = selector.selectedKeys(); Iterator<SelectionKey> iterator = readyKeys.iterator(); while (iterator.hasNext()) { SelectionKey key = iterator.next(); iterator.remove(); try { // 检查事件是否是一个新的已经就绪可以被接受的连接 if(key.isAcceptable()) { ServerSocketChannel server = (ServerSocketChannel)key.channel(); SocketChannel client = server.accept(); client.configureBlocking(false); // 接受客户端,并将它注册到选择器 client.register(selector, SelectionKey.OP_WRITE | SelectionKey.OP_READ, msg.duplicate()); System.out.println("Accepted connection from " + client); } // 检查套接字是否已经准备好写数据 if(key.isWritable()) { SocketChannel client = (SocketChannel)key.channel(); ByteBuffer buffer = (ByteBuffer)key.attachment(); // 将数据写到已连接的客户端 while(buffer.hasRemaining()) { if(client.write(buffer) == 0) { break; } } // 关闭连接 client.close(); } } catch (IOException ex) { key.cancel(); try { key.channel().close(); } catch (IOException cex) { // ignore on close } } } } } }
-
Netty 版本的 OIO 和 NIO 在实现上的差异仅仅是
EventLoopGroup
和Channel
类型的差异上,使用方式完全一致 -
Channel
接口是传输API的核心,类层次结构如下,每个Channel
都持有一个ChannelPipeline
和ChannelConfig
,ChannelConfig
中包含了该 Channel 的所有配置设置,并支持热更新
image.png
-
ChannelPipeline
持有所有将应用于入站和出站数据以及事件的ChannelHandler
实例,ChannelHandler
的典型用途:- 将数据从一种格式转换为另一种格式
- 提供异常的通知
- 提供
Channel
变为活动的或者非活动的通知; - 提供当
Channel
注册到EventLoop
或者从EventLoop
注销时的通知; - 提供有关用户自定义事件的通知
-
Netty 内置了可以开箱即用的传输
名称 包 描述 NIO io.netty.channel.socket.nio 使用 java.nio.channels 包作为基础——基于选择器的方式 Epoll io.netty.channel.epoll 由 JNI 驱动的 epoll() 和非阻塞 IO OIO io.netty.channel.socket.oio 使用 java.net 包作为基础——使用阻塞流 Local io.netty.channel.local 可以在 VM 内部通过管道进行通信的本地传输 Embedded io.netty.channel.embedded Embedded 传输,允许使用 ChannelHandler 而又不需要一个真正的基于网络的传输

网友评论