`
spark8090
  • 浏览: 3269 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

mina粘包、多包和少包的解决方法 (转)

阅读更多
mina粘包、多包和少包的解决方法 (转)
原文地址:http://freemart.iteye.com/blog/836654

使用过mina的同学应该都遇到到过,在解码时少包、多包的问题,查阅了很多资料还是迷迷糊糊的,经过

不懈努力,终于解决了。原来解决方法是那样的简单。废话少说,请看列子。
  
   另外建了一个交流群:19702042,大家可以在线交流

   问题:我发送的是xml字符串数据,在发送数据后,接收方在解码的时候可能接到1条,也可能是多条,还

可能是半条或一条半,解决方法就是使用CumulativeProtocolDecoder

   首先,在编码的时候要把前4位设成标志位,标志消息内容的长度。里面的重点是doDecode的返回值,一

定要继承CumulativeProtocolDecoder 哦。

  清看decode的写法
public class AsResponseDecoder extends CumulativeProtocolDecoder {
private static Logger LOG = 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];
   in.mark();//标记当前位置,以便reset
   in.get(sizeBytes);//读取前4字节
                        //NumberUtil是自己写的一个int转byte[]的一个工具类
   int size = NumberUtil.byteArrayToInt(sizeBytes);
   //如果消息内容的长度不够则直接返回true
   if(size > in.remaining()){//如果消息内容不够,则重置,相当于不读取size
    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类
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;
 
  String xml = AsXmlPacker.pack(respCmd);//将对象转成xml
  byte[] bytes = xml.getBytes();
  byte[] sizeBytes = NumberUtil.intToByteArray(bytes.length);
 
  buffer.put(sizeBytes);//将前4位设置成数据体的字节长度
  buffer.put(bytes);//消息内容
  buffer.flip();
  out.write(buffer);
}

}

原文转述完毕、在原文中缺少三个类没有贴出代码、现在我将自己的实现补充在这里
其一 :字节与整数的转换NumberUtil.java
public class NumberUtil {
    public static byte[] intToByte(int i) {
        byte[] abyte0 = new byte[4];
        abyte0[0] = (byte) (0xff & i);
        abyte0[1] = (byte) ((0xff00 & i) >>;
        abyte0[2] = (byte) ((0xff0000 & i) >> 16);
        abyte0[3] = (byte) ((0xff000000 & i) >> 24);
        return abyte0;
    }
    public  static int bytesToInt(byte[] bytes) {
        int addr = bytes[0] & 0xFF;
        addr |= ((bytes[1] << & 0xFF00);
        addr |= ((bytes[2] << 16) & 0xFF0000);
        addr |= ((bytes[3] << 24) & 0xFF000000);
        return addr;
    }

}
其二:对象与xml的相互转换XmlPacker.java
public class XmlPacker {
public XmlPacker(){}
public static void parse(MessageBag msg,String xml){
  XStream xstream = new XStream(new DomDriver()); // does not require XPP3 library
  xstream.fromXML(xml,msg);
}
public static String pack(MessageBag msg){
  XStream xstream = new XStream(new DomDriver()); // does not require XPP3 library
  String xml = xstream.toXML(msg);
  return xml;
}
}
分享到:
评论

相关推荐

    mina 断包,粘包问题解决

    总的来说,Apache Mina为解决网络通信中的断包和粘包问题提供了强大的工具。通过理解和应用mina_optimize代码,你可以更好地掌握如何在实际项目中规避这些问题,提升网络通信的稳定性和可靠性。在实际开发中,结合...

    Mina断包,粘包处理(完整实例,有客户端,服务端)

    总的来说,理解和处理Mina中的断包和粘包问题,需要深入理解网络通信协议、数据编码解码原理以及Mina框架的工作机制。通过分析Android-Mina-master项目中的代码,我们可以学习到如何在实际应用中解决这些问题,提高...

    mina 协议 解包 粘包

    mina 协议 解包 粘包

    mina4-android:Android TCP框架(基于MINA 2.0.0-M3)、增加Bytes工厂、无需依赖slf4j(新增Mina4Log打印输出日志), 处理Bytes粘包、半包、断包(ByteArrayDecoder)

    处理Bytes粘包、半包、断包(ByteArrayDecoder),需配置自己的首尾标识符, 如果与首尾标识符相同的数据出现在首尾标识符以内的范围,建议将该数据进行转义, 如这样配置转义规则(假设首尾标识符是0x7e): 0x7e = 0x...

    springboot mina 串口对接

    综上所述,SpringBoot与Mina的结合,使我们能够方便地在Java应用程序中实现串口通信,解决粘包和断包问题,同时可能借助WebSocket实现与Web客户端的交互。"treatment_serial_service"作为核心组件,是串口通信功能的...

    HPsocket 封包与mina对接

    ### HPsocket 封包与mina对接 #### 一、HPsocket概述 ...通过设置合适的包头标识、包体长度和缓冲区大小等参数,以及在Mina中正确配置过滤器和处理器,可以有效地解决断包、粘包等问题,实现稳定可靠的网络通信。

    Java视频教程 Java游戏服务器端开发 Netty NIO AIO Mina视频教程

    jaca视频教程 jaca游戏服务器端开发 Netty NIO AIO Mina视频教程 课程目录: 一、Netty快速入门教程 01、第一课NIO 02、第二课netty服务端 03、第三课netty客户端 04、第四课netty线程模型源码分析(一) 05、...

    Voovan开发手册

    - **起源**:Voovan项目起源于开发者在使用Netty和Mina框架过程中遇到的一些难点和困惑,尤其是关于粘包等问题的处理。这促使开发者进一步研究Java异步通信机制,并最终决定基于Java 1.7之后引入的AIO(Asynchronous...

    面向智能相机的远程异步图像数据处理服务.pdf

    为了解决这一问题,南京邮电大学的研究人员潘钺、胡健和孟庆琳提出了一种面向智能相机的远程异步图像数据处理服务,旨在通过服务器端对智能相机并发图像数据进行处理,并提供了一个整体的服务框架。 这项服务首先在...

    Java Netty 分布式开发 框架

    Netty的组件和设计使其在分布式系统的网络通信中表现出色,比如处理消息分段、粘包和半包问题、心跳检测、重连机制等。它的扩展性允许开发者针对特定的业务需求开发插件。例如,在处理用户登录时,可以添加一个...

    Java面试题10道Java高级必备的Netty面试题!.pdf

    - 如何处理粘包和拆包问题,以及如何选择合适的FrameDecoder? 6. **零拷贝** - 什么是零拷贝?Netty是如何实现零拷贝的? - 零拷贝在什么场景下能显著提高性能? 7. **心跳机制** - 在Netty中如何实现心跳...

    Java Netty-入门教程.pdf

    - 对常见的问题如粘包、半包现象提供了有效的解决方案。 - 避免了 epoll 空轮询导致的 CPU 资源浪费问题。 - 对 Java 标准库中的 API 进行了增强和优化,提高了使用的便利性和效率。 - **相比于其他网络应用框架*...

Global site tag (gtag.js) - Google Analytics