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 ...
随机推荐
- extern int *a与extern int a[]
extern int *a与int a[] Table of Contents 1. 问题: 2. 解答: 1 问题: 以下的声明取自某个源文件: int a[10]; int *b=a; 但在还有一 ...
- SQL Server 2008备份数据库失败,拒绝访问的原因
原文:SQL Server 2008备份数据库失败,拒绝访问的原因 备份数据到特定目录是出现拒绝访问,然后测试备份到C盘根目录正常. 查了下原因: 是因为那个目录没有Authenticated Use ...
- (转)一篇很不错的介绍Eclipse插件Menu及其扩展点的文章
原文在:http://tech.ddvip.com/2010-04/1271054623150507.html 菜单是各种软件及开发平台会提供的必备功能,Eclipse 也不例外,提供了丰富的菜单,包 ...
- EF一次请求公用一个实例
应用场景: 我们在程序开发时,对数据库的操作是必不可少的部分,常规的做法是直接使用Using()语句块,在用完后立即释放连接资源,这种做法在桌面应用程序中毫无问题,但是在Web程序中,尤其是在当今大数 ...
- Java流读写
写: package com.wjy.write; import java.io.BufferedWriter; import java.io.FileOutputStream; import jav ...
- 配置JVM内存 查看内存工具
一.配置JVM内存 1.配置JVM内存的參数有四个: -XmxJavaHeap最大值.默认值为物理内存的1/4.最佳设值应该视物理内存大小及计算机内其它内存开销而定. -XmsJavaHeap初始值, ...
- Justinmind教程(3)——管理原型
如已经描述Justinmind概述和Justinmind简单的计算器功能 Justinmind使用教程(1)--概述部分 Justinmind使用教程(2)--计算表达式及条件用法 本章将回到最原始的 ...
- Oracle练习
--声明一个变量,并给它赋值 declare v_bonus number(8); begin select id*6 into v_bonus from A where Id=5; DBMS_OU ...
- "最大工作进程数"导致的WCF调用失败
WCF服务寄宿在IIS中,当设置其“最大工作进程数”>1时,经常会出现服务无法被成功调用 客户端异常为System.ServiceModel.Security.MessageSecurityEx ...
- Oracle SQL Lesson (3) - 使用单行函数自定义输出
大小写转换函数LOWER('SQL Course') = sql courseUPPER('SQL Course') = SQL COURSEINITCAP('SQL Course') = Sql C ...