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;
}
}
未完侍加
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 ...
随机推荐
- ueditor编辑器和at.js集成
源码: <%@ page language="java" import="java.util.*" pageEncoding="UTF-8&qu ...
- Origin的图片导出问题
很多会议投稿都会要求提交的pdf文件用的是type1字体,因为type1字体是矢量字体,无论怎么放大缩小都不会失真.一旦pdf里嵌入了其他非矢量字体,例如type3字体,就会通不过测试,一个典型的例子 ...
- Javascript--练习(包括主界面图片轮播效果)
练习一 例子1:做一个问题,如果输入的答案正确则弹出正确,错误弹出错误: 这里在text里面写了一个daan属性,里面存了答案的值,点击检查答案的时候cheak输入的内容和答案是否一样: Body中代 ...
- 关于网卡eth0、eth1以及服务器为什么要把内网和外网卡区分开
在搜搜上看到了这个回答,它解释了什么是eth0,eth1: eth0和eth1这是网卡设备,只是个名称不必纠结.通常服务器会有多个网卡的,所以就有eth0 eth1 eth2 这样的名称,而且在一些系 ...
- paip.配置ef_unified_filter() failed ext_filter_module mod_ext_filter.so apache 错误解决
paip.配置ef_unified_filter() failed ext_filter_module mod_ext_filter.so apache 错误解决 作者Attilax 艾龙, ...
- Leetcode 257 Binary Tree Paths 二叉树 DFS
找到所有根到叶子的路径 深度优先搜索(DFS), 即二叉树的先序遍历. /** * Definition for a binary tree node. * struct TreeNode { * i ...
- Leetcode 119 Pascal's Triangle II 数论递推
杨辉三角,这次要输出第rowIndex行 用滚动数组t进行递推 t[(i+1)%2][j] = t[i%2][j] + t[i%2][j - 1]; class Solution { public: ...
- android定位GPS定位 代码实现
package com.lx.util; import android.content.Context; import android.content.SharedPreferences; imp ...
- How to get blob data using javascript XmlHttpRequest by sync
Tested: Firefox 33+ OK Chrome 38+ OK IE 6 -- IE 10 Failed Thanks to 阮一峰's blog: http://www.ruanyifen ...
- 阿里云产品介绍(三):云数据库RDS
写完云服务器ECS,本来想先写负载均衡的. 因为发现很多客户,都是直接将单台云服务器应用对外提供访问,如果云服务器宕机,应用就会停止服务.云服务器标称有99.95%的可用率,一年下来宕机四个多小时也是 ...