粘包和分包出现的原因是:没有一个稳定数据结构

解决办法: 分割符

     长度 + 数据

* <pre>  
* 数据包格式
* +——----——+——-----——+——----——+——----——+——-----——+
* | 包头 | 模块号 | 命令号 | 长度 | 数据 |
* +——----——+——-----——+——----——+——----——+——-----——+
* </pre>
* 包头4字节
* 模块号2字节short
* 命令号2字节short
* 长度4字节(描述数据部分字节长度)

创建encoder  和 decoder  分别 加入pipeline 中

public class RpcDecoder extends ByteToMessageDecoder {

    private Class<?> genericClass;

    public RpcDecoder(Class<?> genericClass) {
this.genericClass = genericClass;
} @Override
public void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
if (in.readableBytes() < 4) {
return;
}
in.markReaderIndex();
int dataLength = in.readInt();
if (dataLength < 0) {
ctx.close();
}
if (in.readableBytes() < dataLength) {
in.resetReaderIndex();
return;
}
byte[] data = new byte[dataLength];
in.readBytes(data); Object obj = SerializationUtil.deserialize(data, genericClass);
out.add(obj);
}
}
public class RpcEncoder extends MessageToByteEncoder {

    private Class<?> genericClass;

    public RpcEncoder(Class<?> genericClass) {
this.genericClass = genericClass;
} @Override
public void encode(ChannelHandlerContext ctx, Object in, ByteBuf out) throws Exception {
if (genericClass.isInstance(in)) {
byte[] data = SerializationUtil.serialize(in);
out.writeInt(data.length);
out.writeBytes(data);
}
}
}
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
if (in.readableBytes() >= BASE_LENGTH) { //防止socket字节流攻击
if (in.readableBytes() > 2048) {
in.skipBytes(in.readableBytes());
} //记录包头开始的index
int beginReader; //读取包头
while (true) {
beginReader = in.readerIndex();
in.markReaderIndex();
if (in.readInt() == Constantvalue.FLAG) {
break;
} //未读到包头, 略过一个字节
in.resetReaderIndex();
in.readByte(); //长度又变得不满足
if (in.readableBytes() < BASE_LENGTH) {
return;
}
}
} // 模块号
short module = in.readShort();
//命令好
short cmd = in.readShort();
// 长度
int dataLength = in.readInt(); if (in.readableBytes() < dataLength) {
//还原读指针
in.resetReaderIndex();
return;
}
byte[] data = new byte[dataLength];
in.readBytes(data);
Request request = new Request();
request.setModule(module);
request.setCmd(cmd);
request.setData(data);
//继续往下传递
out.add(request); }

buffer里面数据未被读取完怎么办

protected void callDecode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
try {
while (in.isReadable()) {
int outSize = out.size();
int oldInputLength = in.readableBytes();
decode(ctx, in, out); // Check if this handler was removed before continuing the loop.
// If it was removed, it is not safe to continue to operate on the buffer.
//
// See https://github.com/netty/netty/issues/1664
if (ctx.isRemoved()) {
break;
} if (outSize == out.size()) { // 这里会对照长度 先判断读到东西了没有, 没有跳出
if (oldInputLength == in.readableBytes()) { // 读取位置变化没
break;
} else {
continue;
}
} if (oldInputLength == in.readableBytes()) {
throw new DecoderException(
StringUtil.simpleClassName(getClass()) +
".decode() did not read anything but decoded a message.");
} if (isSingleDecode()) {
break;
}
}

数据缓存在 cumulation中

public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
if (msg instanceof ByteBuf) {
RecyclableArrayList out = RecyclableArrayList.newInstance();
try {
ByteBuf data = (ByteBuf) msg;
first = cumulation == null; //第一次请求 cumulation 为 null true
if (first) {
cumulation = data;
} else {
cumulation = cumulator.cumulate(ctx.alloc(), cumulation, data); // 第二次请求时进入 将新的信息追加到cumulation后面
}
callDecode(ctx, cumulation, out);
} catch (DecoderException e) {
throw e;
} catch (Throwable t) {
throw new DecoderException(t);
} finally {
if (cumulation != null && !cumulation.isReadable()) {
cumulation.release();
cumulation = null;
}
int size = out.size(); for (int i = 0; i < size; i ++) {
ctx.fireChannelRead(out.get(i));
}
out.recycle();
}
} else {
ctx.fireChannelRead(msg);
}
}

Netty自定义数据包协议的更多相关文章

  1. 基于Netty的RPC架构学习笔记(十):自定义数据包协议

    文章目录 数据包简介 粘包.分包现象 数据包格式 举个

  2. IM通信协议逆向分析、Wireshark自定义数据包格式解析插件编程学习

    相关学习资料 http://hi.baidu.com/hucyuansheng/item/bf2bfddefd1ee70ad68ed04d http://en.wikipedia.org/wiki/I ...

  3. 在dubbo的一端,看Netty处理数据包,揭网络传输原理

    如今,我们想要开发一个网络应用,那是相当地方便.不过就是引入一个框架,然后设置些参数,然后写写业务代码就搞定了. 写业务代码自然很重要,但是你知道: 你的数据是怎么来的吗?通过网络传输过来的呗. 你知 ...

  4. WebSocket数据包协议详解

    其实我一直想不明白HTML5包装个应用层办议作为Socket通过基础目的是为了什么,其实直接支持Socket tcp相对来说更加简单灵活.既然标准已经制定而浏览器也支持那对于我们开发者来说只能用的分. ...

  5. 【求助】NdisSend,自定义数据包发送失败?

    做ndis hook的时候,自定义了一个数据包,包结构应该没有问题,填充NDIS_PACKET结构是这样的,先初始化:        NdisAllocatePacketPool(&nStat ...

  6. TCP/IP网络编程之数据包协议

    一.概要 在了解了网络字节序之后,接下来就是要讲最最重点的消息协议.数据包是什么呢,数据包可以理解为两个人讲电话说的每一句话的内容.通过大家约定好的方式去理解.达到只有接听电话两个人才懂的东西.在程序 ...

  7. asp.net core中遇到需要自定义数据包解密方法的时候

    最近将公司的项目用.netcore重写, 服务的http外部接口部分收发消息是DES加解密的, 那么在asp.net core mvc的action处理之前需要加入解密这个步骤. 我第一想到的是用fi ...

  8. 示例:Netty 处理 TCP数据分包协议

    一个.Netty解决TCP协议的数据分包的想法 我们知道通过TCP协议发送接收数据时,假设数据过大.接收到的数据会是分包的.比方:                                   ...

  9. 如何实现自定义sk_buff数据包并提交协议栈

    目录 一.自定义数据包的封装流程 1. 分配skb 2.初始定位(skb_reserve) 3.拷贝数据(skb_push / skb_pull / skb_put / ) 4.设置传输层头部 5.设 ...

随机推荐

  1. ansible user模块

    查看模块的功能和选项,使用ansible-doc命令 ansible-doc options: -l #查看所有可用的模块 -m #查看模块的路径 -v #查看版本 -t TYPE #查看插件,插件: ...

  2. Hadoop Aggregate Resource Allocation解释

    1.在hadoop里面运行程序的时候,查看某个任务的具体信息如下: [hadoop@master monitor]$ yarn application -list 如上图,这里面的Aggregate ...

  3. linux搭建代理服务器+蚁剑配置客户端代理

    一:linux搭建代理服务器 0x00 介绍 关于搭建代理服务器的方法,我也是刚刚接触,从网上找了一些能够行得通的方法来给大家做个分享: 这里我用的是Tinyproxy作为代理服务软件.这个东西很小, ...

  4. JS中的常用的代码操作

    本文件介绍常用的js代码的DOM操作.CSS操作.对象(Object对象.Array对象.Number对象.String对象.Math对象.JSON对象和Console对象)操作说明. 一.DOM树的 ...

  5. Arts打卡第7周

    Algorithm.主要是为了编程训练和学习. 每周至少做一个 leetcode 的算法题(先从Easy开始,然后再Medium,最后才Hard). 进行编程训练,如果不训练你看再多的算法书,你依然不 ...

  6. linux下如何删除乱码文件

    首先执行ls -i命令,此时在文件前面会出现一个数字,这个数字是文件的节点号 接着,执行命令 find -inum 节点号 -delete 即可将乱码文件成功删除

  7. Channel继承关系

  8. JDK安装及Java环境变量配置

    1.JDK下载地址:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html. 2.点击A ...

  9. linux和window下生成任意大小的文件

    在Windows环境下的实现方法   使用fsutil命令,在windows xp和win 7下应该都自带了这个命令.命令的格式是 fsutil file createnew 新文件名 文件大小.例如 ...

  10. arcgis python 一个mxd打包mpk

    def onempk(fileName): if fileName: mxd = arcpy.mapping.MapDocument(fileName) else: mxd = arcpy.mappi ...