问题描述
mina在发送长报文时,为什么被截成好几段呢。请大侠帮帮忙。
解决方案
解决方案二:
这个是必然的。物理限制,和mina无关。你使用的默认解码器或者自己写的解码器的一个功能,就是将可能的N个物理包,变成一个逻辑包。每个逻辑包,包头应当由标志位(这个逻辑包是什么数据)以及长度位(这个逻辑包长度是多少,个别固定长度的逻辑包,可以省略)。每次,解码的时候,读取bytebuffer的头,看看当前解析的是什么包,然后长度是多少,再比较一下,当前的bytebuffer长度够不够,如果不够的话,则将bytebuffer的指针重新mark到0,并不处理当前的bytebuffer下次接收到的物理包的bytebuffer会和这次没解析玩的拼在一起,位置还是在这个逻辑包的开头位置,一直到接收到足够的数据。另外,要注意的是,最后一个包,可能还包含下一次的逻辑包的开头部分,在解析完当前包的时候,要注意最后把position设置到正确位置。以免下一个逻辑包丢数据。下面是一个我很早前些的mina1的例子//$Id:AbstractPacketDecoder.java,v1.52008/06/1519:07:27michaelExp$packagexxx.codec.decoder;importorg.apache.commons.logging.Log;importorg.apache.commons.logging.LogFactory;importorg.apache.mina.common.ByteBuffer;importorg.apache.mina.common.IoSession;importorg.apache.mina.filter.codec.ProtocolDecoderOutput;importorg.apache.mina.filter.codec.demux.MessageDecoderAdapter;importorg.apache.mina.filter.codec.demux.MessageDecoderResult;/***数据包解码对象解码器抽象超类。**@version$Revision:1.5$$Date:2008/06/1519:07:27$*@param*<P>*解码器返回的数据包内容*/publicabstractclassAbstractPacketDecoder<P>extendsMessageDecoderAdapter{/***每个数据包头的默认长度:3字节(1位标志位+2位长度位)。*个别标志位下4位长度位或者没有长度位的情况下,请覆盖@{coderetrieveHeaderLength()}方法。*@see#retrieveHeaderLength()*/publicstaticfinalintDEFAULT_HEADER_LENGTH=3;/***日志对象*/protectedfinalLoglog=LogFactory.getLog(getClass());/***数据包类型*/protectedbytetype;/***创建一个新的<code>AbstractPacketDecoder</code>对象。**@paramtype*可以解码的数据类型*/protectedAbstractPacketDecoder(bytetype){this.type=type;}/***判断当前解码器能否解码最新读入的数据。**@paramsession*连接会话*@paramin*读入的字节缓冲*@return是否可解码:{@codeMessageDecoder.OK}可以解码;*{@codeMessageDecoder.NOT_OK}不能解码;*{@codeMessageDecoder.NEED_DATA}需要更多数据才能判断是否能够解码*@seeorg.apache.mina.filter.codec.demux.MessageDecoder#decodable(org.apache.mina.common.IoSession,*org.apache.mina.common.ByteBuffer)*/publicMessageDecoderResultdecodable(IoSessionsession,ByteBufferin){//数据包头长度intheaderLength=retrieveHeaderLength();if(in.remaining()<headerLength){//读入的字节缓冲中的剩余数据长度小于数据包头长度,需要更多数据//注意:即使有标志位便可以确认当前类能否解码,仍然需要确保第一次解码时能够正确读入长度数据returnNEED_DATA;}//数据包类型bytecontentType=in.get();if(contentType==type){//数据包类型与当前解码器可以解码的数据类型匹配,可以解码returnOK;}else{//数据包类型与当前解码器可以解码的数据类型匹配,不能解码returnNOT_OK;}}/***解码最新读入的数据。**@paramsession*会话连接*@paramin*读入的字节缓冲*@paramout*存放解码结果的输出*@return处理结果:{@codeMessageDecoder.OK}可以解码;{@codeMessageDecoder.NOT_OK}*不能解码;{@codeMessageDecoder.NEED_DATA}需要更多数据才能判断是否能够解码*@throwsException*如果在处理中发生异常的话*@seeorg.apache.mina.filter.codec.demux.MessageDecoder#decode(org.apache.mina.common.IoSession,*org.apache.mina.common.ByteBuffer,*org.apache.mina.filter.codec.ProtocolDecoderOutput)*/publicMessageDecoderResultdecode(IoSessionsession,ByteBufferin,ProtocolDecoderOutputout)throwsException{//记录原有位置in.mark();//跳过数据包标志位in.get();//数据包长度intcontentLength=getContentLength(session,in);if(in.remaining()<contentLength){//当前物理数据包长度小于逻辑数据包长度,重置开始位置in.position(in.markValue());//需要更多数据returnNEED_DATA;}//解码数据体Ppacket=decodeBody(session,in,contentLength);if(packet==null){//错误returnNOT_OK;}//保存数据包对象out.write(packet);//解码成功returnOK;}/***返回数据包头的长度。*<p>*针对个别包4位长度位或者没有长度位的情况,子类应该覆盖该方法,返回对应的数据包头长度。*</p>**@return数据包头的长度*/protectedintretrieveHeaderLength(){returnDEFAULT_HEADER_LENGTH;}/***获取数据体(不含标志位及长度位本身)的字节长度。*<p>*本方法会在获取数据包类型后被调用,默认从当前字节缓冲中读取2字节长度信息。*</p>*<p>*子类可以覆盖该方法,直接返回长度信息而不从字节缓冲中读取。*</p>**@paramsession*会话连接*@paramin*字节缓冲*@return数据体长度,它可以是:*<ul>*<li>从数据包中特定位置读取的长度信息</li>*<li><code>NEED_MORE_LENGTH_INFO</code>代表需要更多字节才能判断长度</li>*</ul>*/protectedintgetContentLength(IoSessionsession,ByteBufferin){returnin.getShort();}/***解码数据体内容,并返回对应的数据对象。**@paramsession*会话连接*@paramin*读入的字节缓冲*@paramcontentLength*数据体长度*@return数据体内容解码后得到的对应的数据对象,或者<code>null</code>代表解码时发生错误。*@throwsException*如果在处理中发生异常的话*/protectedabstractPdecodeBody(IoSessionsession,ByteBufferin,intcontentLength)throwsException;}
解决方案三:
该回复于2011-10-31 13:58:16被版主删除
解决方案四:
能不能把你的mina1的例子发给我看看,邮箱xmt1990@126.com