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 网络框架实现(转)的更多相关文章

  1. java nio 网络框架

    https://github.com/solq360/common 主要运行在android 平台 解决自动化编/解码,等等.. 模块 解决问题/实现处理 备注 负责人 进度 录音播放 AudioRe ...

  2. java nio 网络框架实现

    maven项目 https://github.com/solq360/common 链式编/解码 链路层链式处理 管道管理socket 多协议处理非常方便 仿netty NioEventLoop 单线 ...

  3. 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 非阻塞网络编程原 ...

  4. Java NIO通信框架在电信领域的实践

    [http://www.codeceo.com/article/java-nio-communication.html]   华为电信软件技术架构演进 Java NIO框架在技术变迁中起到的关键作用 ...

  5. Java NIO 网络编程基础

    Java NIO提供了一套网络api,可以用来处理连接数很多的情况.他的基本思想就是用一个线程来处理多个channel. 123456789101112131415161718192021222324 ...

  6. JAVA NIO异步通信框架MINA选型和使用的几个细节(概述入门,UDP, 心跳)

    Apache MINA 2 是一个开发高性能和高可伸缩性网络应用程序的网络应用框架.它提供了一个抽象的事件驱动的异步 API,可以使用 TCP/IP.UDP/IP.串口和虚拟机内部的管道等传输方式.A ...

  7. Java NIO网络编程demo

    使用Java NIO进行网络编程,看下服务端的例子 import java.io.IOException; import java.net.InetAddress; import java.net.I ...

  8. 基于NIO的Netty网络框架

    Netty是一个高性能.异步事件驱动的NIO框架,它提供了对TCP.UDP和文件传输的支持,Netty的所有IO操作都是异步非阻塞的,通过Future-Listener机制,用户可以方便的主动获取或者 ...

  9. BIO & NIO & NIO常见框架

    BIO & NIO BIO - Blocking IO - 同步式阻塞式IO --- UDP/TCP NIO - New  IO - 同步式非阻塞式IO AIO  - Asynchronous ...

随机推荐

  1. 乞讨N!到底有多少0

    分析: 对N质因数分解 N=2^x * 3^y * 5^z....因为10 = 2*5,所以末尾0的个数仅仅和x与z有关,每一对2和5相乘能够得到一个10.于是末尾0的个数=min(x,z).在实际中 ...

  2. poj1655(树形dp)

    题目链接:http://poj.org/problem?id=1655 题目大意:给一个树,删除其中一个点就会形成一个森林,点的平衡度为删除了这个节点后,所形成多个树,其中组成树的节点最多,节点个数就 ...

  3. linux--文件夹下批量改动IP

    sed -i 's/10.11/10.22/g' `grep ir 10.11 *| grep -E'.xml:|.cfg:|.ini:|.wsdl|.properties:' |awk -F:'{p ...

  4. 关于split与StringTokenizer的理解

    关于split与StringTokenizer的理解 一.split    依据匹配给定的正則表達式来拆分此字符串.此方法返回的数组包括此字符串的子字符串,每一个子字符串都由还有一个匹配给定表达式的子 ...

  5. freemarker导出word带图片

    导出word带图片 如果你需要在word中添加图片,那你就在第一步制作模板时,加入一张图片占位,然后打开xml文档,可以看到如下的一片base64编码后的代码: <w:binData w:nam ...

  6. 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 ...

  7. WPF命中测试示例(二)——几何区域命中测试

    原文:WPF命中测试示例(二)--几何区域命中测试 接续上次的命中测试,这次来做几何区域测试示例. 示例 首先新建一个WPF项目,在主界面中拖入一个按钮控件,并修改代码中的以下高亮位置: 当前设计视图 ...

  8. 工厂方法模式(factory method pattern)

    工厂方法模式相对于简单工厂模式的长处是为了更好的拓展,当假设再新加一种产品,对于简单工厂模式来说须要改动核心的工厂类,但对于工厂方法模式则不须要,在工厂方法模式中核心的工厂类不再负责创建全部产品的创建 ...

  9. 将Excel数据表到数据库表

    假设你有大量的数据要导入到数据库表,恐怕是没有效率的写程序,作为用于数据操纵,Excel在这方面有优势,但是,如何将其结合起来?将Excel数据表到数据库表,就是本篇博客的目的. 首先去下载MySQL ...

  10. 安装zookeeper集群

    zookeeper集群的安装   顾名思义zookeeper就是动物园管理员,他是用来管hadoop(大象).Hive(蜜蜂).pig(小猪)的管理员, Apache Hbase和 Apache So ...