转载自: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 粘包、多包和少包的解决方法的更多相关文章

  1. adb+tcpdump手机抓包过程出现的报错及解决方法

    tcpdump下载:https://www.androidtcpdump.com/android-tcpdump/downloads 1.夜神模拟器连接不上adb D:1手机木马取证\android- ...

  2. 通过 getResources 找不到jar包中的资源和目录的解决方法

    http://my.oschina.net/sub/blog/184074 今天碰到一个怪问题: 原本跑的好好的代码,打成 jar 包就不能运行了. 问题出在,代码中有一段自动扫描 classpath ...

  3. Spring Boot 打war包后自定义404页面不生效解决方法

    最近做一个项目,自定义了404页面,本地测试可以到自定义页面,但是打包放到tomcat里面就不行.搞了一天终于看到一个比较正确的方法.下面附上连接,非常感谢各位博主们 1.https://blog.c ...

  4. eclipse使用maven install 命令,生成war包中没有jsp/js/css的解决方法

    在pom.xml文件中添加如下11行代码就可以了. <build> <plugins> <plugin> <groupId>org.apache.mav ...

  5. json转换时区问题-------前端展示时间少8小时--解决方法

    在application配置文件中加如下: spring.jackson.time-zone=GMT+8

  6. ueditor的工具栏显示乱码解决方法 小问题.. 是你的页面编码与语言包js编码不符所导致的

    ueditor的工具栏显示乱码解决方法 小问题..  是你的页面编码与语言包js编码不符所导致的解决方法:用记事本将ueditor\..\lang\zh-cn\zh-cn.js打开,然后保存为ANSI ...

  7. maven下载jar包下载不下来的解决方法

    转载请注明出处: 在eclipse中安装了maven插件,项目在运行的时候,一直通过pom.xml文件下载jar包,一直下载不下来, 在更新maven库时,如果网络问不定或者是一些自己手动安装到本地m ...

  8. UNIX网络编程——Socket/TCP粘包、多包和少包, 断包

    为什么TCP 会粘包 前几天,调试mina的TCP通信, 第一个协议包解析正常,第二个数据包不完整.为什么会这样吗,我们用mina这样通信框架,还会出现这种问题? TCP(transport cont ...

  9. Socket/TCP粘包、多包和少包, 断包

    转发: https://blog.csdn.net/pi9nc/article/details/17165171 为什么TCP 会粘包 前几天,调试mina的TCP通信, 第一个协议包解析正常,第二个 ...

随机推荐

  1. oracle学习 十一 包+复合类型+自定义异常(持续更新)

    在这里讲一下包的概念, 二话不说上个例子 包头: create or replace package pck_test is procedure proc_report_salary(name nva ...

  2. JDBC 常用驱动类及url格式

    1. oracle <dependency> <groupId>com.oracle</groupId> <artifactId>ojdbc6</ ...

  3. (图解版)SQL Server数据库备份与还原

        本文介绍了SQL Server数据库备份的两种方式.一种是直接拷贝数据库中的文件mdf 和日志文件ldf,另一种是生成脚本语言. 第一种方式:     选中需要备份的数据库,将数据库从运行的数 ...

  4. 图说Java —— 理解Java机制最受欢迎的8幅图

    原文链接:  Top 8 Diagrams for Understanding Java 翻译人员: 铁锚 翻译时间: 2013年10月29日 世间总是一图胜过千万言! 下面的8幅图来自于 Progr ...

  5. hdoj 5355 Cake(分析+二分)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5355 分蛋糕的题目,有1-n大小的n个蛋糕,要求平均分成m份,不能切开蛋糕 #include<s ...

  6. hdoj 5301 Buildings

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5301 #include <iostream> #include <stdio.h&g ...

  7. logstash开源日志收集查询分析系统

    http://storysky.blog.51cto.com/628458/1158707/ http://www.logstash.net/ http://blog.sina.com.cn/s/bl ...

  8. Weka EM 协方差

    Weka EM covariance description 1: Dear All, I am trying to find out what is the real meaning of the ...

  9. 移动端轮播图插件(支持Zepto和jQuery)

    一. 效果图 二. 功能介绍 1. 支持图片自动轮播和非自动轮播 2. 支持点击和滑动. 三. 简单介绍 代码都有注释,逻辑简单,不做更多赘述. 1. 在你的html中添加一行. <sectio ...

  10. Extjs Google的Suggest的自动提示 从后台取数据

    //服务器取数据 var remoteStore = Ext.create('Ext.data.Store', { proxy: ({ type: "ajax", url:&quo ...