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通信, 第一个协议包解析正常,第二个 ...
随机推荐
- 使用WSAIoctl获取socket扩展函数(如AcceptEx)的指针
未获取函数指针就调用函数(如直接连接mswsock.lib并直接调用AcceptEx)的消耗是很大的,因为AcceptEx 实际上是存在于Winsock2结构体系之外的.每次应用程序常试在服务提供层上 ...
- cf754 A. Lesha and array splitting
应该是做麻烦了,一开始还没A(幸好上一次比赛水惨了) #include<bits/stdc++.h> #define lowbit(x) x&(-x) #define LL lon ...
- 压力测试工具:tsung
http://tsung.erlang-projects.org/user_manual/introduction.html#what-is-tsung
- win10的安装、win10启动盘制作
需要的材料 win10映像 U盘 UltraISO软件 1.下载对应的win10映像 有64位和32位可选(自己找地方下) 2.下载UltraISO软件 3.准备一只U盘,插入电脑 4.启动Ultra ...
- ThinkPHP模板(一)
如何关闭ThinkPHP的模板缓存 ThinkPHP的模板缓存是无奈关闭的,因为内置的模板引擎是一个编译型的模板引擎,必须经过编译后生成一个可执行的缓存文件才能被执行.但是可以设置缓存的有效期,例如设 ...
- COM组件入门(一)
近期须要用到COM组件的知识,看了看COM编程指南,感觉还不错.把我的学习心得记录下来.这是我依据教程写的demo StopWatch接口实现部分,接口部分我的项目是动态库,主要源代码例如以下: 完整 ...
- 【机试题】c# 是否是素数,找出比它大的第一个素数
题目: 输入一个自然数 判断是否是素数,是素数则提示是素数,否则找出比它大的第一个素数 代码: Console.WriteLine("请输入任意一个自然数."); string n ...
- UVALive 4225 Prime Bases 贪心
Prime Bases 题目连接: https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&a ...
- hdu 5286 How far away ? tarjan/lca
How far away ? Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pi ...
- .Net 应用程序如何在32位操作系统下申请超过2G的内存【转】
作者: eaglet 2008 年我写过一篇博客叫 <让.Net 应用程序突破2G的内存访问限制> 这篇博客主要讲述了如何在32位操作系统下利用AWE 扩展访问超过2G的内存.AWE方式虽 ...