文档章节

nio服务端序列图

泡海椒
 泡海椒
发布于 2016/02/17 11:07
字数 616
阅读 32
收藏 4

NIO服务端通信序列图如下:

下面,我们对NIO服务端的主要创建过程进行讲解和说明:

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

?

1
ServerSocketChannel acceptorSvr = ServerSocketChannel.open();

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

?

1
2
acceptorSvr.socket().bind( new  InetSocketAddress(InetAddress.getByName( "IP" ),port));
acceptorSvr.configureBlocking( false );

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

?

1
2
Selector selector = Selector.open();
New Thread( new  ReactorTask()).start();

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

?

1
SelectionKey key = acceptorSvr.register(selector,SelectionKey.OP_ACCEPT,ioHandler);

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

?

1
2
3
4
5
6
7
int  num = selector.select();
Set selectedKey s = selector.selectedKeys();
Iterator it = selectedKeys.iterator();
while (it.hasNext()){
     SelectionKey key = (SelectionKey)it.next();
     // ... deal with I/O event ...
}

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

?

1
SocketChannel channel = svrChannel.accept();

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

?

1
2
3
channel.configureBlocking( false );
channel.socket().setReuseAddress( true );
......

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

?

1
SelectionKey  key = socketChannel.register(selector,SelectionKey.OP_READ);

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

?

1
int  readNumber = channel.read(recelvedBuffer);

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

?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Object message =  null ;
while (buffer.hasRemain()){
     byteBuffer.mark();
     Object message = decode(byteBuffer);
     if (message ==  null ){
         byteBuffer.reset();
         break ;
     }
     messageList.add(message);
}
if (!byteBuffer.hasRemain())
     byteBuffer.clear();
else
     byteBuffer.compact();
if (messageList !=  null  & !messageList.isEmpty()){
     for (Object messageE :messageList)
         handlerTask(messageE);
}

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

?

1
socketChannel.write(buffer);

注意:如果发送区TCP缓冲区满,会导致写半包,此时,需要注册监听写操作位,循环写,直到整包消息写入TCP缓冲区。


© 著作权归作者所有

共有 人打赏支持
下一篇: 伪异步i/o模型
泡海椒
粉丝 11
博文 278
码字总数 286768
作品 0
成都
程序员
私信 提问
Netty高性能之道

背景 1.1. 惊人的性能数据 最近一个圈内朋友通过私信告诉我,通过使用Netty4 + Thrift压缩二进制编解码技术,他们实现了10W TPS(1K的复杂POJO对象)的跨节点远程服务调用。相比于传统基于J...

HenrySun
2016/04/19
119
0
Java异步NIO框架Netty实现高性能高并发

背景 1.1. 惊人的性能数据 最近一个圈内朋友通过私信告诉我,通过使用Netty4 + Thrift压缩二进制编解码技术,他们实现了10W TPS(1K的复杂POJO对象)的跨节点远程服务调用。相比于传统基于J...

java知识分子
09/28
0
0
Java 与 Netty 实现高性能高并发

1. 背景 1.1. 惊人的性能数据 最近一个圈内朋友通过私信告诉我,通过使用Netty4 + Thrift压缩二进制编解码技术,他们实现了10W TPS(1K的复杂POJO对象)的跨节点远程服务调用。相比于传统基于...

ljianbing
2017/04/01
0
0
Netty系列之Netty高性能之道

背景 1.1. 惊人的性能数据 最近一个圈内朋友通过私信告诉我,通过使用Netty4 + Thrift压缩二进制编解码技术,他们实现了10W TPS(1K的复杂POJO对象)的跨节点远程服务调用。相比于传统基于J...

宇智波带土
2014/06/17
0
1
Spring+Netty+Protostuff+ZooKeeper实现轻量级RPC服务

RPC简介 RPC,即 Remote Procedure Call(远程过程调用),说得通俗一点就是:调用远程计算机上的服务,就像调用本地服务一样。 RPC 可基于 HTTP 或 TCP 协议,Web Service 就是基于 HTTP 协...

Listen_ing
2016/05/26
2.3K
12

没有更多内容

加载失败,请刷新页面

加载更多

java单例设计模式

实现方法一 package com.hs.pattern.singleton;/** * 优点:实现简单 * 缺点:线程不安全 * 例如:当两个线程都运行到if( singleton == null ),而singleton确实为空,则两个线程都...

yangyangyyyy
17分钟前
1
0
MacOS下安装MongoDB数据库

官方链接:Install MongoDB Community Edition on macOS 推荐大家使用Homebrew安装 ##1.更新 Homebrew’s 包版本 brew update 2.安装MongoDB brew install mongodb 休息片刻,等他安装完就...

凌宇之蓝
17分钟前
1
0
Linux系统如何定制History输出格式

Linux系统使用History命令来查看系统的运行记录,从而找出一些问题。但是History输出的数据中常常没有时间等信息。本文就来教大家Linux系统如何定制History输出格式。   具体方法如下 以r...

Linux就该这么学
20分钟前
1
0
Add Digits(leetcode258)

Given a non-negative integer num, repeatedly add all its digits until the result has only one digit. Example: Input: 38 Output: 2 Explanation: The process is like: 3 + 8 = 11, 1......

woshixin
21分钟前
1
0
android简洁饼状图组件、圆形Menu菜单、画板画笔应用、答题应用等源码

Android精选源码 android自动监听复制内容源码 Android上简洁轻量级的饼图控件 好看的 Android 圆形 Menu 菜单效果 android画笔、画板功能效果的实现 Android撸一个Android图表框架 支持 It...

Android爱开源
25分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部