maven项目

https://github.com/solq360/common

  • 链式编/解码
  • 链路层链式处理
  • 管道管理socket
  • 多协议处理非常方便
  • 仿netty NioEventLoop 单线程串行处理

========

侍加功能 :

  • 自动化编/解码
  • rpc 接口增强使用

简单聊天例子

server

TestNioServer

  1. //创建session管理工厂
  2. ISessionFactory sessionFactory = new SessionFactory();
  3. //创建编/解码管理
  4. ICoderParserManager coderParserManager = new CoderParserManager();
  5. //注册包编/解码,处理业务
  6. coderParserManager.register(CoderParser.valueOf("server chat", PackageDefaultCoder.valueOf(), new ChatTestServerHandle()));
  7. //创建ServerSocket 实例
  8. ServerSocket serverSocket=ServerSocket.valueOf(SocketChannelConfig.valueOf(6969), 10,20,coderParserManager, sessionFactory);
  9. //启动服务
  10. serverSocket.start();
  11. //阻塞当前线程
  12. serverSocket.sync();
  13. //关闭处理
  14. serverSocket.stop();

client

TestNioClient

传统方式连接

  1. //创建编/解码管理
  2. ICoderParserManager coderParserManager = new CoderParserManager();
  3. //注册包编/解码,处理业务
  4. coderParserManager.register(CoderParser.valueOf("chat", PackageDefaultCoder.valueOf(), new ChatHandle()));
  5. //创建ClientSocket 实例
  6. final ClientSocket clientSocket = ClientSocket.valueOf(SocketChannelConfig.valueOf(6969), new SocketPool("client", null), coderParserManager, new EmptyHandle());
  7. //模拟连接之后发送消息
  8. Timer timer = new Timer();
  9. timer.schedule(new TimerTask() {
  10. @Override
  11. public void run() {
  12. clientSocket.send("连接服务器成功");
  13. System.out.println("send ");
  14. this.cancel();
  15. }
  16. }, 1000);
  17. //启动服务
  18. clientSocket.start();
  19. //阻塞当前线程
  20. clientSocket.sync();
  21. //关闭处理
  22. clientSocket.stop();

服务器方式连接

  1. //创建session管理工厂
  2. ISessionFactory sessionFactory = new SessionFactory();
  3. //创建编/解码管理
  4. ICoderParserManager coderParserManager = new CoderParserManager();
  5. //注册包编/解码,处理业务
  6. coderParserManager.register(CoderParser.valueOf("chat", PackageDefaultCoder.valueOf(), new ChatHandle()));
  7. //创建ClientSocket 实例
  8. final ServerSocket serverSocket = ServerSocket.valueOf(SocketChannelConfig.valueOf(8888), 10, 20, coderParserManager, sessionFactory);
  9. //模拟连接之后发送消息
  10. Timer timer = new Timer();
  11. timer.schedule(new TimerTask() {
  12. @Override
  13. public void run() {
  14. System.out.println("registerClientSocket");
  15. //主动连接服务器
  16. ClientSocket clientSocket = serverSocket.registerClient(SocketChannelConfig.valueOf(6969));
  17. clientSocket.send("连接服务器成功");
  18. this.cancel();
  19. }
  20. }, 1000);
  21. //启动服务
  22. serverSocket.start();
  23. //阻塞当前线程
  24. serverSocket.sync();
  25. //关闭处理
  26. serverSocket.stop();

源码实现过程

链式编/解码

  • 由 多个 ICoder 输入/输出转换处理
  • CoderParser 类组装多个 ICoder
  • 编/码处理器 注意优先级
  • nio read -> packageCoder -> link coders -> handle
  • handle write -> link coders -> packageCoder -> nio write
  • 由 ICoderParserManager 管理调用处理
  1. public interface ICoderParserManager {
  2. /**
  3. * 解码处理
  4. *
  5. * @return CoderResult
  6. * */
  7. CoderResult decode(ByteBuffer buffer, ICoderCtx ctx);
  8. /**
  9. * 编码处理
  10. * */
  11. ByteBuffer encode(Object message, ICoderCtx ctx);
  12. void error(ByteBuffer buffer, ICoderCtx ctx);
  13. /** 注册 编/码处理器 */
  14. void register(CoderParser coderParser);
  15. }

其中核心

decode

encode

  1. @Override
  2. public CoderResult decode(ByteBuffer buffer, ICoderCtx ctx) {
  3. final SocketChannelCtx socketChannelCtx = (SocketChannelCtx) ctx;
  4. final ClientSocket clientSocket = socketChannelCtx.getClientSocket();
  5. for (CoderParser coderParser : coderParsers.values()) {
  6. final IPackageCoder packageCoder = coderParser.getPackageCoder();
  7. final ICoder<?, ?>[] linkCoders = coderParser.getCoders();
  8. final IHandle handle = coderParser.getHandle();
  9. Object value = null;
  10. synchronized (buffer) {
  11. // 已解析完
  12. if (socketChannelCtx.getCurrPackageIndex() >= buffer.limit()) {
  13. return CoderResult.valueOf(ResultValue.UNFINISHED);
  14. }
  15. // 包协议处理
  16. if (!packageCoder.verify(buffer, ctx)) {
  17. continue;
  18. }
  19. // 包解析
  20. value = packageCoder.decode(buffer, ctx);
  21. if (value == null) {
  22. // 包未读完整
  23. return CoderResult.valueOf(ResultValue.UNFINISHED);
  24. }
  25. }
  26. // 链式处理
  27. if (linkCoders != null) {
  28. for (ICoder coder : linkCoders) {
  29. value = coder.decode(value, ctx);
  30. if (value == null) {
  31. throw new CoderException("解码出错 : " + coder.getClass());
  32. }
  33. }
  34. }
  35. // 业务解码处理
  36. value = handle.decode(value, ctx);
  37. clientSocket.readBefore(socketChannelCtx, value);
  38. handle.handle(value, ctx);
  39. clientSocket.readAfter(socketChannelCtx, value);
  40. return CoderResult.valueOf(ResultValue.SUCCEED);
  41. }
  42. return CoderResult.valueOf(ResultValue.NOT_FIND_CODER);
  43. }
  44. @Override
  45. public ByteBuffer encode(Object message, ICoderCtx ctx) {
  46. for (CoderParser coderParser : coderParsers.values()) {
  47. final IPackageCoder packageCoder = coderParser.getPackageCoder();
  48. final ICoder<?, ?>[] linkCoders = coderParser.getCoders();
  49. final IHandle handle = coderParser.getHandle();
  50. // 业务检查
  51. if (!handle.verify(message, ctx)) {
  52. continue;
  53. }
  54. // 业务编码处理
  55. Object value = handle.encode(message, ctx);
  56. // 链式处理
  57. if (linkCoders != null) {
  58. for (int i = linkCoders.length - 1; i >= 0; i--) {
  59. ICoder coder = linkCoders[i];
  60. value = coder.encode(value, ctx);
  61. if (value == null) {
  62. throw new CoderException("编码出错 : " + coder.getClass());
  63. }
  64. }
  65. }
  66. // 打包消息处理
  67. value = packageCoder.encode(value, ctx);
  68. if (value != null) {
  69. return (ByteBuffer) value;
  70. }
  71. throw new CoderException("编码出错 :" + packageCoder.getClass());
  72. }
  73. throw new CoderException("未找到编/解码处理器 ");
  74. }
  • 半包/帖包处理 : AbstractISocketChannel doRead方法摘要,根据解码返回的状态做处理。
  • 半包:当不是完成状态时,继续解码,从最后一次包索引开始处理
  • 帖包:当完成包解码移动包索引,等侍下轮解码处理
  1. boolean run = true;
  2. // 粘包处理
  3. while (run) {
  4. ByteBuffer cpbuffer = socketChannelCtx.coderBegin();
  5. cpbuffer.mark();
  6. CoderResult coderResult = coderParserManager.decode(cpbuffer, socketChannelCtx);
  7. switch (coderResult.getValue()) {
  8. case SUCCEED:
  9. break;
  10. case NOT_FIND_CODER:
  11. final int readySize = socketChannelCtx.getWriteIndex() - socketChannelCtx.getCurrPackageIndex();
  12. final int headLimit = 255;
  13. if (readySize >= headLimit) {
  14. throw new CoderException("未找到编/解码处理器 ");
  15. }
  16. run = false;
  17. break;
  18. case UNFINISHED:
  19. case UNKNOWN:
  20. case ERROR:
  21. default:
  22. run = false;
  23. // TODO throw
  24. break;
  25. }
  26. }

未完侍加

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. latex数字加粗后变宽

    latex的数字默认用的是Times New Roman字体,这个字体有个不优美之处就是加粗后会变宽,如下图所示: 平常倒是也无所谓.昨天在把实验数据整理进表格时,为了凸显每个数据集上各个实验方法的优 ...

  2. paip.提升性能---协程“微线程”的使用.

    paip.提升性能---协程的使用. 近乎无限并发的"微线程" 作者Attilax  艾龙,  EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:h ...

  3. atitit.条形码的原理与生成总结java Barcode4j barcode o5

    atitit.条形码的原理与生成总结java Barcode4j barcode o5 条形码类库使用报告Barcode4j, ZXing 1 使用成果图片 1 条形码标准code 128和code  ...

  4. paip.解决 数据库mysql增加列 字段很慢添加字段很慢

    paip.解决 数据库mysql增加列 字段很慢添加字段很慢 #环境如下: mysql5.6    数据仅仅3w alter table xxx add column yyy int default ...

  5. paip.代码生成器数据源格式最佳实践

    paip.代码生成器数据源格式最佳实践 需要满足几个条件. 1.基于文本 2.容易的编辑.. 3,容易的代码解析. 这样,常用的设计工具powerdesign cdm pdm就排除兰...cdm虽然是 ...

  6. SQL Server 添加链接服务器

    背景 在SQL SERVER中,如果我们查询数据库需要关联另外一台数据库中表,在这种情况下我们可以通过添加服务器链接来实现. 案列 方式1.sql server 提供了图形化界面,如下: 右键> ...

  7. Android WebView Memory Leak WebView内存泄漏

    在这次开发过程中,需要用到webview展示一些界面,但是加载的页面如果有很多图片就会发现内存占用暴涨,并且在退出该界面后,即使在包含该webview的Activity的destroy()方法中,使用 ...

  8. LPC4370 ACDHS speed and DMA

    LPC4370 ACDHS speed AHB clock BASE_M4_CLK CLK_M4_ADCHS up to 204 MHz. For register interface. ADCHS ...

  9. CentOS6.5下安装Open vSwitch

    准备 # yum install openssl-devel redhat-rpm-config kernel-devel -y #yum install kvm libvirt python-vir ...

  10. eclipse web项目转maven项目

    ps:好久没写博客了,工作了人就懒了,加油加油,up,up 1 eclipse web项目目录 /web app src com.xx.xx *.properties *.xml WebRoot ​W ...