java nio 网络框架实现(转)
maven项目
https://github.com/solq360/common
- 链式编/解码
- 链路层链式处理
- 管道管理socket
- 多协议处理非常方便
- 仿netty NioEventLoop 单线程串行处理
========
侍加功能 :
- 自动化编/解码
- rpc 接口增强使用
简单聊天例子
server
TestNioServer
//创建session管理工厂
ISessionFactory sessionFactory = new SessionFactory();
//创建编/解码管理
ICoderParserManager coderParserManager = new CoderParserManager();
//注册包编/解码,处理业务
coderParserManager.register(CoderParser.valueOf("server chat", PackageDefaultCoder.valueOf(), new ChatTestServerHandle()));
//创建ServerSocket 实例
ServerSocket serverSocket=ServerSocket.valueOf(SocketChannelConfig.valueOf(6969), 10,20,coderParserManager, sessionFactory);
//启动服务
serverSocket.start();
//阻塞当前线程
serverSocket.sync();
//关闭处理
serverSocket.stop();
client
TestNioClient
传统方式连接
//创建编/解码管理
ICoderParserManager coderParserManager = new CoderParserManager();
//注册包编/解码,处理业务
coderParserManager.register(CoderParser.valueOf("chat", PackageDefaultCoder.valueOf(), new ChatHandle()));
//创建ClientSocket 实例
final ClientSocket clientSocket = ClientSocket.valueOf(SocketChannelConfig.valueOf(6969), new SocketPool("client", null), coderParserManager, new EmptyHandle());
//模拟连接之后发送消息
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
clientSocket.send("连接服务器成功");
System.out.println("send ");
this.cancel();
}
}, 1000);
//启动服务
clientSocket.start();
//阻塞当前线程
clientSocket.sync();
//关闭处理
clientSocket.stop();
服务器方式连接
//创建session管理工厂
ISessionFactory sessionFactory = new SessionFactory();
//创建编/解码管理
ICoderParserManager coderParserManager = new CoderParserManager();
//注册包编/解码,处理业务
coderParserManager.register(CoderParser.valueOf("chat", PackageDefaultCoder.valueOf(), new ChatHandle()));
//创建ClientSocket 实例
final ServerSocket serverSocket = ServerSocket.valueOf(SocketChannelConfig.valueOf(8888), 10, 20, coderParserManager, sessionFactory);
//模拟连接之后发送消息
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("registerClientSocket");
//主动连接服务器
ClientSocket clientSocket = serverSocket.registerClient(SocketChannelConfig.valueOf(6969));
clientSocket.send("连接服务器成功");
this.cancel();
}
}, 1000);
//启动服务
serverSocket.start();
//阻塞当前线程
serverSocket.sync();
//关闭处理
serverSocket.stop();
源码实现过程
链式编/解码
- 由 多个 ICoder 输入/输出转换处理
- CoderParser 类组装多个 ICoder
- 编/码处理器 注意优先级
- nio read -> packageCoder -> link coders -> handle
- handle write -> link coders -> packageCoder -> nio write
- 由 ICoderParserManager 管理调用处理
public interface ICoderParserManager {
/**
* 解码处理
*
* @return CoderResult
* */
CoderResult decode(ByteBuffer buffer, ICoderCtx ctx);
/**
* 编码处理
* */
ByteBuffer encode(Object message, ICoderCtx ctx);
void error(ByteBuffer buffer, ICoderCtx ctx);
/** 注册 编/码处理器 */
void register(CoderParser coderParser);
}
其中核心
decode
encode
@Override
public CoderResult decode(ByteBuffer buffer, ICoderCtx ctx) {
final SocketChannelCtx socketChannelCtx = (SocketChannelCtx) ctx;
final ClientSocket clientSocket = socketChannelCtx.getClientSocket();
for (CoderParser coderParser : coderParsers.values()) {
final IPackageCoder packageCoder = coderParser.getPackageCoder();
final ICoder<?, ?>[] linkCoders = coderParser.getCoders();
final IHandle handle = coderParser.getHandle();
Object value = null;
synchronized (buffer) {
// 已解析完
if (socketChannelCtx.getCurrPackageIndex() >= buffer.limit()) {
return CoderResult.valueOf(ResultValue.UNFINISHED);
}
// 包协议处理
if (!packageCoder.verify(buffer, ctx)) {
continue;
}
// 包解析
value = packageCoder.decode(buffer, ctx);
if (value == null) {
// 包未读完整
return CoderResult.valueOf(ResultValue.UNFINISHED);
}
}
// 链式处理
if (linkCoders != null) {
for (ICoder coder : linkCoders) {
value = coder.decode(value, ctx);
if (value == null) {
throw new CoderException("解码出错 : " + coder.getClass());
}
}
}
// 业务解码处理
value = handle.decode(value, ctx);
clientSocket.readBefore(socketChannelCtx, value);
handle.handle(value, ctx);
clientSocket.readAfter(socketChannelCtx, value);
return CoderResult.valueOf(ResultValue.SUCCEED);
}
return CoderResult.valueOf(ResultValue.NOT_FIND_CODER);
}
@Override
public ByteBuffer encode(Object message, ICoderCtx ctx) {
for (CoderParser coderParser : coderParsers.values()) {
final IPackageCoder packageCoder = coderParser.getPackageCoder();
final ICoder<?, ?>[] linkCoders = coderParser.getCoders();
final IHandle handle = coderParser.getHandle();
// 业务检查
if (!handle.verify(message, ctx)) {
continue;
}
// 业务编码处理
Object value = handle.encode(message, ctx);
// 链式处理
if (linkCoders != null) {
for (int i = linkCoders.length - 1; i >= 0; i--) {
ICoder coder = linkCoders[i];
value = coder.encode(value, ctx);
if (value == null) {
throw new CoderException("编码出错 : " + coder.getClass());
}
}
}
// 打包消息处理
value = packageCoder.encode(value, ctx);
if (value != null) {
return (ByteBuffer) value;
}
throw new CoderException("编码出错 :" + packageCoder.getClass());
}
throw new CoderException("未找到编/解码处理器 ");
}
- 半包/帖包处理 : AbstractISocketChannel doRead方法摘要,根据解码返回的状态做处理。
- 半包:当不是完成状态时,继续解码,从最后一次包索引开始处理
帖包:当完成包解码移动包索引,等侍下轮解码处理
boolean run = true;
// 粘包处理
while (run) {
ByteBuffer cpbuffer = socketChannelCtx.coderBegin();
cpbuffer.mark();
CoderResult coderResult = coderParserManager.decode(cpbuffer, socketChannelCtx);
switch (coderResult.getValue()) {
case SUCCEED:
break;
case NOT_FIND_CODER:
final int readySize = socketChannelCtx.getWriteIndex() - socketChannelCtx.getCurrPackageIndex();
final int headLimit = 255;
if (readySize >= headLimit) {
throw new CoderException("未找到编/解码处理器 ");
}
run = false;
break;
case UNFINISHED:
case UNKNOWN:
case ERROR:
default:
run = false;
// TODO throw
break;
}
}
http://www.cnblogs.com/solq/p/4585496.html
java nio 网络框架实现(转)的更多相关文章
- java nio 网络框架
https://github.com/solq360/common 主要运行在android 平台 解决自动化编/解码,等等.. 模块 解决问题/实现处理 备注 负责人 进度 录音播放 AudioRe ...
- java nio 网络框架实现
maven项目 https://github.com/solq360/common 链式编/解码 链路层链式处理 管道管理socket 多协议处理非常方便 仿netty NioEventLoop 单线 ...
- Netty | 第1章 Java NIO 网络编程《Netty In Action》
目录 前言 1. Java 网络编程 1.1 Javs NIO 基本介绍 1.2 缓冲区 Buffer 1.2 通道 Channel 1.3 选择器 Selector 1.4 NIO 非阻塞网络编程原 ...
- Java NIO通信框架在电信领域的实践
[http://www.codeceo.com/article/java-nio-communication.html] 华为电信软件技术架构演进 Java NIO框架在技术变迁中起到的关键作用 ...
- Java NIO 网络编程基础
Java NIO提供了一套网络api,可以用来处理连接数很多的情况.他的基本思想就是用一个线程来处理多个channel. 123456789101112131415161718192021222324 ...
- JAVA NIO异步通信框架MINA选型和使用的几个细节(概述入门,UDP, 心跳)
Apache MINA 2 是一个开发高性能和高可伸缩性网络应用程序的网络应用框架.它提供了一个抽象的事件驱动的异步 API,可以使用 TCP/IP.UDP/IP.串口和虚拟机内部的管道等传输方式.A ...
- Java NIO网络编程demo
使用Java NIO进行网络编程,看下服务端的例子 import java.io.IOException; import java.net.InetAddress; import java.net.I ...
- 基于NIO的Netty网络框架
Netty是一个高性能.异步事件驱动的NIO框架,它提供了对TCP.UDP和文件传输的支持,Netty的所有IO操作都是异步非阻塞的,通过Future-Listener机制,用户可以方便的主动获取或者 ...
- BIO & NIO & NIO常见框架
BIO & NIO BIO - Blocking IO - 同步式阻塞式IO --- UDP/TCP NIO - New IO - 同步式非阻塞式IO AIO - Asynchronous ...
随机推荐
- 乞讨N!到底有多少0
分析: 对N质因数分解 N=2^x * 3^y * 5^z....因为10 = 2*5,所以末尾0的个数仅仅和x与z有关,每一对2和5相乘能够得到一个10.于是末尾0的个数=min(x,z).在实际中 ...
- poj1655(树形dp)
题目链接:http://poj.org/problem?id=1655 题目大意:给一个树,删除其中一个点就会形成一个森林,点的平衡度为删除了这个节点后,所形成多个树,其中组成树的节点最多,节点个数就 ...
- linux--文件夹下批量改动IP
sed -i 's/10.11/10.22/g' `grep ir 10.11 *| grep -E'.xml:|.cfg:|.ini:|.wsdl|.properties:' |awk -F:'{p ...
- 关于split与StringTokenizer的理解
关于split与StringTokenizer的理解 一.split 依据匹配给定的正則表達式来拆分此字符串.此方法返回的数组包括此字符串的子字符串,每一个子字符串都由还有一个匹配给定表达式的子 ...
- freemarker导出word带图片
导出word带图片 如果你需要在word中添加图片,那你就在第一步制作模板时,加入一张图片占位,然后打开xml文档,可以看到如下的一片base64编码后的代码: <w:binData w:nam ...
- 64位CentOS5.6安装Mysql 5.5.11GA
1.更新并查看当前CentOS版本是否为5.6yum updatelsb_release -a 2.下载文件下载 bison-2.4.3.tar.gz到/usr/local/src下载 cmake-2 ...
- WPF命中测试示例(二)——几何区域命中测试
原文:WPF命中测试示例(二)--几何区域命中测试 接续上次的命中测试,这次来做几何区域测试示例. 示例 首先新建一个WPF项目,在主界面中拖入一个按钮控件,并修改代码中的以下高亮位置: 当前设计视图 ...
- 工厂方法模式(factory method pattern)
工厂方法模式相对于简单工厂模式的长处是为了更好的拓展,当假设再新加一种产品,对于简单工厂模式来说须要改动核心的工厂类,但对于工厂方法模式则不须要,在工厂方法模式中核心的工厂类不再负责创建全部产品的创建 ...
- 将Excel数据表到数据库表
假设你有大量的数据要导入到数据库表,恐怕是没有效率的写程序,作为用于数据操纵,Excel在这方面有优势,但是,如何将其结合起来?将Excel数据表到数据库表,就是本篇博客的目的. 首先去下载MySQL ...
- 安装zookeeper集群
zookeeper集群的安装 顾名思义zookeeper就是动物园管理员,他是用来管hadoop(大象).Hive(蜜蜂).pig(小猪)的管理员, Apache Hbase和 Apache So ...