博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
自定义数据包协议
阅读量:3725 次
发布时间:2019-05-22

本文共 3574 字,大约阅读时间需要 11 分钟。

自定义数据包协议

代码地址

粘包 分包

两条消息

give me a coffee   give me a tea
give me a coffeegive me a tea   粘包现象
give me a coffeegive me a tea     分包现象

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

  • 分割符

give me a coffee|give me a tea|give me a coffee|give me a tea|
  • 长度 + 数据

16give me a coffee13give me a tea16give me a coffee13give me a tea

数据包结构

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

代码

import org.jboss.netty.buffer.ChannelBuffer;import org.jboss.netty.channel.Channel;import org.jboss.netty.channel.ChannelHandlerContext;import org.jboss.netty.handler.codec.frame.FrameDecoder;import com.cn.common.constant.ConstantValue;import com.cn.common.model.Request;/** * 请求解码器 * 
 * 数据包格式 * +——----——+——-----——+——----——+——----——+——-----——+ * | 包头          | 模块号        | 命令号      |  长度        |   数据       | * +——----——+——-----——+——----——+——----——+——-----——+ * 
* 包头4字节 * 模块号2字节short * 命令号2字节short * 长度4字节(描述数据部分字节长度) * * * */public class RequestDecoder extends FrameDecoder{ /** * 数据包基本长度 */ public static int BASE_LENTH = 4 + 2 + 2 + 4; @Override protected Object decode(ChannelHandlerContext arg0, Channel arg1, ChannelBuffer buffer) throws Exception { //可读长度必须大于基本长度 if(buffer.readableBytes() >= BASE_LENTH){ //防止socket字节流攻击 if(buffer.readableBytes() > 2048){ buffer.skipBytes(buffer.readableBytes()); } //记录包头开始的index int beginReader; while(true){ beginReader = buffer.readerIndex(); buffer.markReaderIndex(); if(buffer.readInt() == ConstantValue.FLAG){ break; } //未读到包头,略过一个字节 buffer.resetReaderIndex(); buffer.readByte(); //长度又变得不满足 if(buffer.readableBytes() < BASE_LENTH){ return null; } } //模块号 short module = buffer.readShort(); //命令号 short cmd = buffer.readShort(); //长度 int length = buffer.readInt(); //判断请求数据包数据是否到齐 if(buffer.readableBytes() < length){ //还原读指针 buffer.readerIndex(beginReader); return null; } //读取data数据 byte[] data = new byte[length]; buffer.readBytes(data); Request request = new Request(); request.setModule(module); request.setCmd(cmd); request.setData(data); //继续往下传递 return request; } //数据包不完整,需要等待后面的包来 return null; }}
import org.jboss.netty.buffer.ChannelBuffer;import org.jboss.netty.buffer.ChannelBuffers;import org.jboss.netty.channel.Channel;import org.jboss.netty.channel.ChannelHandlerContext;import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;import com.cn.common.constant.ConstantValue;import com.cn.common.model.Request;/** * 请求编码器 * 
 * 数据包格式 * +——----——+——-----——+——----——+——----——+——-----——+ * | 包头          | 模块号        | 命令号      |  长度        |   数据       | * +——----——+——-----——+——----——+——----——+——-----——+ * 
* 包头4字节 * 模块号2字节short * 命令号2字节short * 长度4字节(描述数据部分字节长度) * * * */public class RequestEncoder extends OneToOneEncoder{ @Override protected Object encode(ChannelHandlerContext context, Channel channel, Object rs) throws Exception { Request request = (Request)(rs); ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); //包头 buffer.writeInt(ConstantValue.FLAG); //module buffer.writeShort(request.getModule()); //cmd buffer.writeShort(request.getCmd()); //长度 buffer.writeInt(request.getDataLength()); //data if(request.getData() != null){ buffer.writeBytes(request.getData()); } return buffer; }}
/** * 请求对象 * * */public class Request {	/**	 * 请求模块	 */	private short module;	/**	 * 命令号	 */	private short cmd;	/**	 * 数据部分	 */	private byte[] data;}

转载地址:http://iclnn.baihongyu.com/

你可能感兴趣的文章
Web前端——软件和网页的概述
查看>>
Web前端——HTML概述
查看>>
Web前端——HTML实体
查看>>
Web前端——HTML中的标签
查看>>
Web前端——HTML中的列表、表格、表单
查看>>
Web前端——HTML中的超链接
查看>>
Web前端——HTML图片标签
查看>>
计算机网络——物理层
查看>>
Github的使用
查看>>
数据结构——概述
查看>>
计算机网络——网络层
查看>>
Python基本图形绘制
查看>>
Python常用库的使用
查看>>
面向对象与UML
查看>>
python程序的流程控制结构
查看>>
EA构建静态、动态模型图
查看>>
Python序列类型及操作
查看>>
Python字典类型及操作
查看>>
Python集合类型及操作
查看>>
Python文件与异常
查看>>