《Netty 权威指南》—— 服务端序列图

来源:互联网 发布:倒计时小软件 编辑:程序博客网 时间:2024/05/21 10:59
转自:


http://ifeve.com/netty-2-3-2/

声明:本文是《Netty 权威指南》的样章,感谢博文视点授权并发编程网站发布样章,禁止以任何形式转载此文。

下面,我们对NIO服务端的主要创建过程进行讲解和说明,作为NIO的基础入门,我们将忽略掉一些在生产环境中部署所需要的一些特性和功能。

步骤一:打开ServerSocketChannel,用于监听客户端的连接,它是所有客户端连接的父管道,代码示例如下:

查看源代码
打印帮助
1ServerSocketChannel acceptorSvr = ServerSocketChannel.open();

步骤二:绑定监听端口,设置连接为非阻塞模式,示例代码如下:

查看源代码
打印帮助
1acceptorSvr.socket().bind(newInetSocketAddress(InetAddress.getByName(“IP”), port));
2acceptorSvr.configureBlocking(false);

步骤三:创建Reactor线程,创建多路复用器并启动线程,代码如下:

查看源代码
打印帮助
1Selector selector = Selector.open();
2New Thread(newReactorTask()).start();

步骤四:将ServerSocketChannel注册到Reactor线程的多路复用器Selector上,监听ACCEPT事件,代码如下:

查看源代码
打印帮助
1SelectionKey key = acceptorSvr.register( selector, SelectionKey.OP_ACCEPT, ioHandler);

步骤五:多路复用器在线程run方法的无限循环体内轮询准备就绪的Key,代码如下:

查看源代码
打印帮助
1int num = selector.select();
2Set selectedKeys = selector.selectedKeys();
3Iterator it = selectedKeys.iterator();
4while (it.hasNext()) {
5     SelectionKey key = (SelectionKey)it.next();
6     // ... deal with I/O event ...
7}

步骤六:多路复用器监听到有新的客户端接入,处理新的接入请求,完成TCP三次握手,建立物理链路,代码示例如下:

查看源代码
打印帮助
1SocketChannel channel = svrChannel.accept();

步骤七:设置客户端链路为非阻塞模式,示例代码如下:

查看源代码
打印帮助
1channel.configureBlocking(false);
2channel.socket().setReuseAddress(true);

步骤八:将新接入的客户端连接注册到Reactor线程的多路复用器上,监听读操作,用来读取客户端发送的网络消息,代码如下:

查看源代码
打印帮助
1SelectionKey key = socketChannel.register( selector, SelectionKey.OP_READ, ioHandler);

步骤九:异步读取客户端请求消息到缓冲区,示例代码如下:

查看源代码
打印帮助
1int  readNumber =  channel.read(receivedBuffer);

步骤十:对ByteBuffer进行编解码,如果有半包消息指针reset,继续读取后续的报文,将解码成功的消息封装成Task,投递到业务线程池中,进行业务逻辑编排,示例代码如下:

查看源代码
打印帮助
01Object message = null;
02while(buffer.hasRemain())
03{
04       byteBuffer.mark();
05       Object message = decode(byteBuffer);
06       if(message == null)
07       {
08          byteBuffer.reset();
09          break;
10       }
11       messageList.add(message );
12}
13if (!byteBuffer.hasRemain())
14byteBuffer.clear();
15else
16    byteBuffer.compact();
17if (messageList != null & !messageList.isEmpty())
18{
19for(Object messageE : messageList)
20   handlerTask(messageE);
21}

步骤十一:将POJO对象encode成ByteBuffer,调用SocketChannel的异步write接口,将消息异步发送给客户端,示例代码如下:

查看源代码
打印帮助
1socketChannel.write(buffer);

注意:如果发送区TCP缓冲区满,会导致写半包,此时,需要注册监听写操作位,循环写,直到整包消息写入TCP缓冲区,此处不赘述,后续Netty源码分析章节会详细分析Netty的处理策略。
当我们了解创建NIO服务端的基本步骤之后,下面我们将前面的时间服务器程序通过NIO重写一遍,让大家能够学习到完整版的NIO服务端创建。

1

NIO服务端通信序列图

  1. 《Netty 权威指南》—— NIO客户端序列图
  • 《Netty 权威指南》—— NIO创建的TimeServer源码分析
  • 《Netty 权威指南》—— NIO创建的TimeClient源码分析
  • 《Netty 权威指南》样章
  • 《Netty 权威指南》—— AIO 创建的TimeServer源码分析
  • 《Netty 权威指南》—— NIO类库简介
  • 《Netty 权威指南》—— 传统的BIO编程
  • 《Netty 权威指南》—— AIO版本时间服务器运行结果
  • 《Netty 权威指南》—— AIO创建的TimeClient源码分析
  • 《Netty 权威指南》—— 4种IO的对比
  • 《Netty 权威指南》—— 伪异步IO编程
  • 《Netty 权威指南》—— 选择Netty的理由
  • Netty 5用户指南
  • Netty-Mina深入学习与对比(一)
  • Netty-Mina深入学习与对比(二)

    1. 0 0
      原创粉丝点击