mina 粘包、多包和少包的解决方法
转载自:http://freemart.iteye.com/blog/836654
使用过 mina 的同学应该都遇到到过,在解码时少包、多包的问题,查阅了很多资料还是迷迷糊糊的,经过不懈努力,终于解决了。
原来解决方法是那样的简单。废话少说,请看例子。
另外建了一个交流群:19702042,大家可以在线交流
问题:
我发送的是 xml 字符串数据,在发送数据后,接收方在解码的时候可能接到1条,
也可能是多条,还可能是半条或一条半,解决方法就是使用 CumulativeProtocolDecoder
首先,在编码的时候要把前 4 位设成标志位,标志消息内容的长度。
里面的重点是 doDecode 的返回值,一定要继承 CumulativeProtocolDecoder 哦。
请看 decode 的写法:
package org.bruce.mina.cpp.codec; import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder; import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; public class AsResponseDecoder extends CumulativeProtocolDecoder {
private static Logger logger = LoggerFactory.getLogger(AsResponseDecoder.class);
private final Charset charset; public AsResponseDecoder(Charset charset) {
this.charset = charset;
} /**
* 这个方法的返回值是重点:
* 1、当内容刚好时,返回 false,告知父类接收下一批内容
*
* 2、内容不够时需要下一批发过来的内容,此时返回 false,
* 这样父类 CumulativeProtocolDecoder 会将内容放进 IoSession 中,
* 等下次来数据后就自动拼装再交给本类的 doDecode
*
* 3、当内容多时,返回 true,因为需要再将本批数据进行读取,
* 父类会将剩余的数据再次推送本类的doDecode
*/
public boolean doDecode(IoSession session, IoBuffer in,
ProtocolDecoderOutput out) throws Exception { CharsetDecoder cd = charset.newDecoder();
if (in.remaining() > 0) {
// 有数据时,读取 4 字节判断消息长度
byte [] sizeBytes = new byte[4]; // 标记当前位置,以便 reset
in.mark(); //读取前 4 字节
in.get(sizeBytes); // NumberUtil 是自己写的一个 int 转 byte[] 的一个工具类
int size = NumberUtil.byteArrayToInt(sizeBytes); if (size > in.remaining()) {
// 如果消息内容的长度不够,则重置(相当于不读取 size),返回 false
in.reset();
// 接收新数据,以拼凑成完整数据
return false; } else {
byte[] bytes = new byte[size];
in.get(bytes, 0, size);
String xmlStr = new String(bytes,"UTF-8");
System.out.println("------------" + xmlStr);
if (null != xmlStr && xmlStr.length() > 0) {
AsResponse resCmd = new AsResponse();
AsXmlPacker.parse(resCmd, xmlStr);
if (resCmd != null) {
out.write(resCmd);
}
}
if (in.remaining() > 0) {
// 如果读取内容后还粘了包,就让父类把剩下的数据再给解析一次
return true;
}
}
}
// 处理成功,让父类进行接收下个包
return false;
} }
下面附上 encode 类
package org.bruce.mina.cpp.codec; import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder; import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolEncoderAdapter;
import org.apache.mina.filter.codec.ProtocolEncoderOutput; public class AsResponseEncoder extends ProtocolEncoderAdapter {
private final Charset charset; public AsResponseEncoder(Charset charset) {
this.charset = charset;
} public void encode(IoSession session, Object message,
ProtocolEncoderOutput out) throws Exception {
CharsetEncoder ce = charset.newEncoder();
IoBuffer buffer = IoBuffer.allocate(100).setAutoExpand(true); AsResponse respCmd = (AsResponse) message; // 将对象转成 xml
String xml = AsXmlPacker.pack(respCmd);
byte[] bytes = xml.getBytes();
byte[] sizeBytes = NumberUtil.intToByteArray(bytes.length); // 将前 4 位设置成数据体的字节长度
buffer.put(sizeBytes);
// 消息内容
buffer.put(bytes);
buffer.flip(); out.write(buffer);
} }
mina 粘包、多包和少包的解决方法的更多相关文章
- adb+tcpdump手机抓包过程出现的报错及解决方法
tcpdump下载:https://www.androidtcpdump.com/android-tcpdump/downloads 1.夜神模拟器连接不上adb D:1手机木马取证\android- ...
- 通过 getResources 找不到jar包中的资源和目录的解决方法
http://my.oschina.net/sub/blog/184074 今天碰到一个怪问题: 原本跑的好好的代码,打成 jar 包就不能运行了. 问题出在,代码中有一段自动扫描 classpath ...
- Spring Boot 打war包后自定义404页面不生效解决方法
最近做一个项目,自定义了404页面,本地测试可以到自定义页面,但是打包放到tomcat里面就不行.搞了一天终于看到一个比较正确的方法.下面附上连接,非常感谢各位博主们 1.https://blog.c ...
- eclipse使用maven install 命令,生成war包中没有jsp/js/css的解决方法
在pom.xml文件中添加如下11行代码就可以了. <build> <plugins> <plugin> <groupId>org.apache.mav ...
- json转换时区问题-------前端展示时间少8小时--解决方法
在application配置文件中加如下: spring.jackson.time-zone=GMT+8
- ueditor的工具栏显示乱码解决方法 小问题.. 是你的页面编码与语言包js编码不符所导致的
ueditor的工具栏显示乱码解决方法 小问题.. 是你的页面编码与语言包js编码不符所导致的解决方法:用记事本将ueditor\..\lang\zh-cn\zh-cn.js打开,然后保存为ANSI ...
- maven下载jar包下载不下来的解决方法
转载请注明出处: 在eclipse中安装了maven插件,项目在运行的时候,一直通过pom.xml文件下载jar包,一直下载不下来, 在更新maven库时,如果网络问不定或者是一些自己手动安装到本地m ...
- UNIX网络编程——Socket/TCP粘包、多包和少包, 断包
为什么TCP 会粘包 前几天,调试mina的TCP通信, 第一个协议包解析正常,第二个数据包不完整.为什么会这样吗,我们用mina这样通信框架,还会出现这种问题? TCP(transport cont ...
- Socket/TCP粘包、多包和少包, 断包
转发: https://blog.csdn.net/pi9nc/article/details/17165171 为什么TCP 会粘包 前几天,调试mina的TCP通信, 第一个协议包解析正常,第二个 ...
随机推荐
- JS鼠标滑轮事件的写法和按键的事件
在body注册一下滑轮事件 <body onload="win_onload();"></body> 然后JS代码如下: function win_onlo ...
- 遇见了这个问题:App.config提示错误“配置系统未能初始化”
解决办法查找之后居然是这样的,受教了,记录一下 解决: "如果配置文件中包含 configSections 元素,则 configSections 元素必须是 configuration 元 ...
- oracle学习 八 分页(使用rownumber)(持续更)
rownumber是查询的数据集之后加入一个伪列(连续的)使用它可以去制作以oracle数据库为基础的分页,语句类似于公式直接套用如下: select * from (select rownum r, ...
- php二叉树算法
二叉树的每个结点至多只有二棵子树(不存在度大于2的结点),二叉树的子树有左右之分,次序不能颠倒.二叉树的第i层至多有2^{i-1}个结点:深度为k的二叉树至多有2^k-1个结点:对任何一棵二叉树T,如 ...
- Git版本管理:Windows下Git配置与使用指南
简要介绍:Git是一个开源的分布式版本控制系统,用以有效.高速的处理从很小到非常大的项目版本管理. 一.安装 软件:msysGit-fullinstall-1.8.1.2 打开之后设置安装路径,默认为 ...
- CloudStack 4.2 与CloudStack 4.1二级存储API发生变化
CloudStack 4.1查看二级存储 http://192.168.150.16:8080/client/api?command=listHosts&response=json&s ...
- springboot 学习笔记(一)
引子 最近在搞一个项目,走在科技前沿的师兄, 摒弃了公司老套的框架模式, 采用了springboot搭建新应用.看到如此简洁的代码 , 深受诱惑.趁周末闲余之时, 背晒阳光, 学起了springboo ...
- head first-----------adpter pattern
head first-----------------深入浅出适配器模式 适配器模式:将一个类的接口,转换成客户想要的另外一个接口,适配器然原本接口不兼容的类可以合作无间.从而可以不用更改旧 ...
- 如何提高数据库update更新的速度
不用不知道,一用吓一跳..看下面这条SQL语句 String sql="update cats set name_alias='"+rs.getString(1)+"'w ...
- Why we need interfaces in Delphi
http://sergworks.wordpress.com/2011/12/08/why-we-need-interfaces-in-delphi/ Why we need interfaces i ...