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. jQuery中的getJSON()

    json文件是一种轻量级的数据交互格式.一般在jQuery中使用getJSON()方法读取. $.getJSON(url,[data],[callback]) url:json文件地址 data:可选 ...

  2. Knockout应用开发指南 第六章:加载或保存JSON数据

    原文:Knockout应用开发指南 第六章:加载或保存JSON数据 加载或保存JSON数据 Knockout可以实现很复杂的客户端交互,但是几乎所有的web应用程序都要和服务器端交换数据(至少为了本地 ...

  3. SVN 的revert操作

  4. HDU 2825 AC自动机+DP

    题意:一个密码,长度为 n,然后有m个magic words,这个密码至少由k个magic words组成. 问这个密码可能出现的总数. 思路:首先构造AC自动机,由于m很小,才10 ,我们可以使用二 ...

  5. 九度 题目1044:Pre-Post

    转载请注明本文链接http://blog.csdn.net/yangnanhai93/article/details/40658571 题目链接:pid=1044">http://ac ...

  6. An Overview of Complex Event Processing

    An Overview of Complex Event Processing 复杂事件处理技术概览(一) 翻译前言:我在理解复杂事件处理(CEP)方面一直有这样的困惑--为什么这种计算模式是有效的, ...

  7. libyuv编

     下载代码(墙): git clone http://git.chromium.org/external/libyuv.git 用 make 编译(linux.mingw.cygwin): mak ...

  8. 【剑指offer】两个队列实现堆栈

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/25076689     题目:用两个队列模拟一个栈,即用两个队列的出队和入队操作.来实现栈的 ...

  9. Eclipse4.4.2手动安装Veloeclipse-2.0.8

    引言:     新安装了Eclipse最新版本 4.4.2 Luna(月神),由于项目中使用到了模板引擎Velocity,所以想安装一个Velocity插件, 在网上找了一下,看到Google的vel ...

  10. 使用dom4j创建和解析xml

    之前工作中用到了,相信写java的都会碰到xml,这里写了两个方法,创建和解析xml,废话不多说,直接上代码 package xml; import java.io.File; import java ...