【MinaFile】【十三】【2.0】关于粘包的处理
来源:互联网 发布:java前端面试 编辑:程序博客网 时间:2024/05/03 10:32
我们在Mina服务器对文件进行自定义解码的时候,继承了类CumulativeProtocolDecoder。
这个类默认的字节数处理是2048,所以当文件超过了2048个字节之后,服务器解码器就会报错java.nio.BufferUnderflowException 这个异常。
以为需要解析的字节为4096KB,但是Mina能够一次性处理的只有2048个字节,所以就会报错。很简单吧?
解决办法,重写一下第【十一】章里面的ByteProtocalDecoder类
/** * 这个是服务器对客户端发来的消息进行解码 * 继承CumulativeProtocolDecoder * 实现doDecode * 父类会将数据读取完之后,再调用实现的方法doDecode。 * 如果成功读取完之后,服务器会去Handle中进行业务处理。 * 对发来的文件进行业务处理,比如说保存之类的 动作。 * @author king_fu * */public class ByteProtocalDecoder extends CumulativeProtocolDecoder{private static final Logger LOGGER = LoggerFactory.getLogger(ByteProtocalDecoder.class);public static final int MAX_FILE_SIZE = 1024 * 1024 * 1024; // 1Gprivate boolean isFinish = false; // 是否已经处理所有数据private static boolean isFirst = true; // 是否是第一次进来private ByteFileMessage bfm = new ByteFileMessage(); // 保存对象private static IoBuffer newIoBuffer = IoBuffer.allocate(0).setAutoExpand(true) ;public ByteProtocalDecoder() {}@Overrideprotected boolean doDecode(IoSession session, IoBuffer in,ProtocolDecoderOutput out) throws Exception {LOGGER.info("服务器对客户端发来的消息进行解码。解码开始");LOGGER.info("limit:"+in.limit());LOGGER.info("remaining:"+in.remaining());try{ // 这个方法的调用是判断IoBuffer里的数据是否满足一条消息了// dataLength = getInt(position());用绝对值的方式读取,position不会移动。 if ((!isFirst) || in.prefixedDataAvailable(4, MAX_FILE_SIZE)) { this.readFile(in); if(isFinish){ // 解析完成 out.write(bfm); }else{ return true; } }else{ in.position(0); LOGGER.info("不符合读取条件"); return false; }}catch (Exception e) {LOGGER.info("服务器解码过程中发生错误",e);return false;}return true;}private void readFile(IoBuffer in) throws CharacterCodingException {CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder();in.position(0);// ByteFileMessage bfm = new ByteFileMessage();if(isFirst){bfm.setSeq(in.getInt()); //序号bfm.setFileNameLength(in.getInt()); // 文件名长度(字节)bfm.setFileName(in.getString(bfm.getFileNameLength(),decoder)); // 文件名。UTF-8格式bfm.setFileStreamLength(in.getInt()); // 文件长度(字节)}//如果读的文件的长度(字节:比如4096个字节),远远大于这个缓冲区的容量(最大容量:2048字节),那么需要进行把一个个包黏起来byte[] byteValue = null;if(bfm.getFileStreamLength() > in.limit()){/*int dealDataLen = in.limit(); // 本次要处理的数据长度byteValue = new byte[dealDataLen];*/bfm.setFileStreamLength(bfm.getFileStreamLength() - in.limit());IoBuffer bufTmp = null;if(isFirst){ // 第一次LOGGER.info("【服务器解析】继续接受in:" + in.remaining());bufTmp = IoBuffer.allocate(newIoBuffer.remaining() +in.remaining() ).setAutoExpand(true);isFirst = false;}else{LOGGER.info("【服务器解析】继续接受in:" + in.remaining());bufTmp = IoBuffer.allocate(newIoBuffer.remaining() + in.remaining() ).setAutoExpand(true);}bufTmp.order(newIoBuffer.order());bufTmp.put(newIoBuffer);bufTmp.put(in);bufTmp.flip();newIoBuffer = bufTmp;isFinish = false; // 数据未读取完。LOGGER.info("【服务器解析】未解析数据:" + newIoBuffer.remaining() + "字节");}else{IoBuffer bufTmp = IoBuffer.allocate( newIoBuffer.remaining() + in.remaining() ).setAutoExpand(true);bufTmp.order(newIoBuffer.order());bufTmp.put(newIoBuffer);bufTmp.put(in);bufTmp.flip();newIoBuffer = bufTmp;int remainingData = newIoBuffer.remaining(); // 总共多少LOGGER.info("【服务器解析】文件需要解析多少字节:" + remainingData);byteValue = new byte[remainingData];newIoBuffer.get(byteValue);LOGGER.info("当前读取的文件大小:" + remainingData/1024 + "KB" );bfm.setFileStream(byteValue);isFinish = true;LOGGER.info("【服务器解析】解析完成");}//LOGGER.info(new String(). bfm.getFileStream());//return isFinish; }}
最新代码已经更新在github中,欢迎fork。
项目名:MinaFile
1 0
- 【MinaFile】【十三】【2.0】关于粘包的处理
- 【MinaFile】【十四】【2.0】多文件处理粘包之服务器接收端
- 【MinaFile】【十五】【2.0】多文件处理粘包之客户端接收端
- 【MinaFile】【六】【2.0】配置文件
- 【MinaFile】【十六】【2.0】总结
- 【MinaFile】【九】【2.0】客户端和服务器的handle的实现
- 【MinaFile】【十二】【2.0】测试服务器和客户端的交互
- 关于tcp粘包的处理
- 关于TCP粘包和半包的处理
- 【MinaFile】【八】【2.0】项目Model
- 【MinaFile】【十】【2.0】自定义异常
- 【MinaFile】【十一】【2.0】实现客户端与服务器交互的自定义编码解码器
- 【MinaFile】【七】【2.0】客户端以及服务器
- c# Socket通讯中关于粘包,半包的处理,加分割符
- 【MinaFile】【四】编写Mina客户端和处理类
- 关于java NIO socket处理粘包 断包问题
- OpenFire源码学习之二十三:关于消息的优化处理
- Java Executor并发框架(十三)Executor框架线程池关于异常的处理
- 淫欲的真相是什么呢?可能很多英雄豪杰都没有想到过
- Linux文件操作 -- lseek实践
- git:branch is published (but not merged) and is now commits behind
- hdoj--1258--Sum It Up(dfs)
- java学习心得——添加列表查询功能
- 【MinaFile】【十三】【2.0】关于粘包的处理
- 论__HashCode和内容Length做快速去重有多不靠谱
- POJ3641 快速幂
- 7216:Minecraft题解
- hdoj 2680 Choose the best route【最短路 dijkstra && SPFA】
- [Python for data Analysis]Python Basic
- Android Studio2.0 Beta 2版本更新说明及注意事项
- 修改Eclipse与MyEclipse的代码提示功能+取消空格上屏
- shell grep常用选项