生活随笔
收集整理的這篇文章主要介紹了
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];// 標記當前位置,以便 resetin.mark();//讀取前 4 字節in.get(sizeBytes);// NumberUtil 是自己寫的一個 int 轉 byte[] 的一個工具類int size = NumberUtil.byteArrayToInt(sizeBytes);if (size > in.remaining()) {// 如果消息內容的長度不夠,則重置(相當于不讀取 size),返回 falsein.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;// 將對象轉成 xmlString 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);}}
轉載于:https://www.cnblogs.com/java20130723/p/3212028.html
總結
以上是生活随笔為你收集整理的mina 粘包、多包和少包的解决方法的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。