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通信, 第一个协议包解析正常,第二个 ... 
随机推荐
- POJ2299Ultra-QuickSort (线段树和归并排序的解法)
			题目大意就是说帮你给一些(n个)乱序的数,让你求冒泡排序需要交换数的次数(n<=500000) 此题最初真不会做,我也只是在听了章爷的讲解后才慢慢明白过来的 首先介绍线段树的解法: 我们先将原数 ... 
- mvc4帮助类
			@App @AppState @Ajax @Cache @Context @Culture @Html @IsPost @Layout @Model @Output @OutputStack @Pag ... 
- mac下xampp简单虚拟主机配置
			多域名,虚拟主机的配置 开启虚拟主机配置选项: 打开httpd.conf文件,找到httpd-vhosts.conf那一行,解除该行注释: 打开httpd-vhosts.conf文件 修改如下 < ... 
- EXTJS AJAX解析XML数据
			public String getAllAreaInfos() { try { List<Areainfo> list = null; if(areaName!=null&& ... 
- php safe mode bypass all <转>
			PHP safe mode bypass from 4.x to 5.x all. Functions: * mb_send_mail* curl_init* imap_open* mail* ion ... 
- Object-C基础
			cocoa 类: 传统的写法:Demo.h // // Demo.h // demoClass // // Created by 王 on 13-12-16. // Copyright (c) 201 ... 
- 编程异常——假设你报createSQLQuery is not valid without active transaction,...
			非常多时候我们使用hibernate的session时,都是让session在某一执行环境中保持其唯一. 比如在同一线程内用同一个session.在同一方法内用同一session,这样我们就能够用se ... 
- [转]Swift Cheat Sheet
			原文:http://kpbp.github.io/swiftcheatsheet/ A quick cheat sheet and reference guide for Apple's Swift ... 
- 调研js模板引擎
			js模板引擎越来越多的得到应用,如今已经出现了几十种js模板引擎,国内各大互联网公司也都开发了自己的js模板引擎(淘宝的kissy template,腾讯的artTemplate,百度的baiduTe ... 
- [Angular2 Form] Style Validation in Angular 2 Forms
			Inputs using Angular 2’s ngModel automatically apply style classes of .ng-validand .ng-invalid each ... 
