posts - 5, comments - 0, trackbacks - 0, articles - 0
            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

          日歷

          <2011年9月>
          28293031123
          45678910
          11121314151617
          18192021222324
          2526272829301
          2345678

          搜索

          •  

          最新評論

            使用過mina的同學應該都遇到到過,在解碼時少包、多包的問題,查閱了很多資料還是迷迷糊糊的,經過

          不懈努力,終于解決了。原來解決方法是那樣的簡單。廢話少說,請看列子。
            
             另外建了一個交流群:19702042,大家可以在線交流

             問題:我發送的是xml字符串數據,在發送數據后,接收方在解碼的時候可能接到1條,也可能是多條,還

          可能是半條或一條半,解決方法就是使用CumulativeProtocolDecoder

             首先,在編碼的時候要把前4位設成標志位,標志消息內容的長度。里面的重點是doDecode的返回值,一

          定要繼承CumulativeProtocolDecoder 哦。

             清看decode的寫法:
          Java代碼 復制代碼 收藏代碼
          1. public class AsResponseDecoder extends CumulativeProtocolDecoder {   
          2.     private static Logger LOG = LoggerFactory.getLogger(AsResponseDecoder.class);   
          3.     private final Charset charset;   
          4.        
          5.     public AsResponseDecoder(Charset charset){   
          6.         this.charset = charset;   
          7.     }   
          8.        
          9.   
          10.     /**  
          11.      * 這個方法的返回值是重點:  
          12.      * 1、當內容剛好時,返回false,告知父類接收下一批內容  
          13.      * 2、內容不夠時需要下一批發過來的內容,此時返回false,這樣父類  
          14.  
          15. CumulativeProtocolDecoder  
          16.      *    會將內容放進IoSession中,等下次來數據后就自動拼裝再交給本類的doDecode  
          17.      * 3、當內容多時,返回true,因為需要再將本批數據進行讀取,父類會將剩余的數據再次推送本  
          18.  
          19. 類的doDecode  
          20.      */  
          21.     public boolean doDecode(IoSession session, IoBuffer in,   
          22.             ProtocolDecoderOutput out) throws Exception {   
          23.            
          24.         CharsetDecoder cd = charset.newDecoder();   
          25.         if(in.remaining() > 0){//有數據時,讀取4字節判斷消息長度   
          26.             byte [] sizeBytes = new byte[4];   
          27.             in.mark();//標記當前位置,以便reset   
          28.             in.get(sizeBytes);//讀取前4字節   
          29.                         //NumberUtil是自己寫的一個int轉byte[]的一個工具類   
          30.             int size = NumberUtil.byteArrayToInt(sizeBytes);   
          31.             //如果消息內容的長度不夠則直接返回true   
          32.             if(size > in.remaining()){//如果消息內容不夠,則重置,相當于不讀取size   
          33.                 in.reset();   
          34.                 return false;//接收新數據,以拼湊成完整數據   
          35.             } else{   
          36.                 byte[] bytes = new byte[size];    
          37.                 in.get(bytes, 0, size);   
          38.                 String xmlStr = new String(bytes,"UTF-8");   
          39.                 System.out.println("------------"+xmlStr);   
          40.                 if(null != xmlStr && xmlStr.length() > 0){   
          41.                     AsResponse resCmd = new AsResponse();   
          42.                     AsXmlPacker.parse(resCmd, xmlStr);   
          43.                     if(resCmd != null){   
          44.                         out.write(resCmd);   
          45.                     }   
          46.                 }   
          47.                 if(in.remaining() > 0){//如果讀取內容后還粘了包,就讓父類再給俺   
          48.   
          49. 一次,進行下一次解析   
          50.                     return true;   
          51.                 }   
          52.             }   
          53.         }   
          54.         return false;//處理成功,讓父類進行接收下個包   
          55.     }   
          56.   
          57.   
          58. }  

          下面附上Encode類
          Java代碼 復制代碼 收藏代碼
          1. public class AsResponseEncoder extends ProtocolEncoderAdapter {   
          2.     private final Charset charset;   
          3.        
          4.     public AsResponseEncoder(Charset charset){   
          5.         this.charset = charset;   
          6.     }   
          7.        
          8.     public void encode(IoSession session, Object message,   
          9.         ProtocolEncoderOutput out) throws Exception {   
          10.         CharsetEncoder ce = charset.newEncoder();   
          11.         IoBuffer buffer = IoBuffer.allocate(100).setAutoExpand(true);   
          12.            
          13.         AsResponse respCmd = (AsResponse) message;   
          14.            
          15.         String xml = AsXmlPacker.pack(respCmd);//將對象轉成xml   
          16.         byte[] bytes = xml.getBytes();   
          17.         byte[] sizeBytes = NumberUtil.intToByteArray(bytes.length);   
          18.            
          19.         buffer.put(sizeBytes);//將前4位設置成數據體的字節長度   
          20.         buffer.put(bytes);//消息內容   
          21.         buffer.flip();   
          22.         out.write(buffer);   
          23.     }   
          24.   
          25.   
          26. }  

            JDK   ByteBuffer

             

            屬性:

            Mark

            上次position的快照

            Position

            當前讀寫索引未知

            Limit

            緩沖區限制

            Capacity

            緩沖區能力

            Offset

            偏移量

             

            說明:

            • Position(Mark)<=limit<=capacity
            • position==limit時就沒有字節可讀寫了
            • 每次getput都將增加position
            • 重置mark就是設置mark=-1

             

             

            方法:

            Limit(int)

            如果position>limit, position = limit,如果mark>limit, 重置mark

            Mark()

            取當前的position的快照標記mark

            Reset()

            恢復position到先前標記的mark

            Clear()

            limit=capacity , position=0,重置mark,但是不清空數據,為了從頭開始put做準備,其實就是清空數據,因為你put就覆蓋了原來的數據

            Rewind()

            position=0,重置mark,一系列寫操作后,為了從頭開始get做準備,和clear()有用途上的區別,他大部分是用來從頭開始讀取,而clear是大部分用來重頭開始填充,就是清理的意思

            Flip()

            limit=position , position=0,重置mask,為了將buf寫出做好準備,一般是結束buf操作,將buf寫入輸出流時調用,這個必須要調用,否則極有可能position!=limit,導致position后面沒有數據,每次寫入數據到輸出流時,必須確保position=limit

            Remaining()

            返回limit-position,返回緩沖器中的剩余字節

            Wrap(byte[])

            組裝到新的buffercapacity=limit=byte[].lengthposition=0 重置mark

            Slice()

            分割緩沖器,將remaining的空間形成一個新的buffer,新的position=0limit=capacity=remaining,重置mark,和主緩沖區內容共享,其它都獨立

            Duplicate()

            復制緩沖區,內容共享,其它都獨立

            asReadOnlyBuffer()

            和duplicate一樣,只是不可寫

            Compact()

            positionlimit之間的字節移到最前面,position=limit-position,這就是這里的壓縮的意思,一般是結束buf操作,將buf寫入輸出流時調用

            Position(int)

            position=newPosition,如果position<mark,重置mark

            Remaining()

            返回positionlimit之間的字節數

           

           

          JDK ByteBuffer

          Mina IoBuffer

          動態擴展capacity

          支持String讀寫

          線程安全

          可主動釋放緩沖區占用內存


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 调兵山市| 延庆县| 平泉县| 宝兴县| 凤翔县| 山东| 岳普湖县| 佳木斯市| 徐州市| 剑川县| 武功县| 志丹县| 永济市| 岢岚县| 沁源县| 格尔木市| 观塘区| 根河市| 临城县| 门源| 绥阳县| 广水市| 无锡市| 双江| 临武县| 南城县| 裕民县| 新宁县| 陵川县| 东阿县| 读书| 仁化县| 沙湾县| 利辛县| 惠东县| 宁南县| 涿鹿县| 瓦房店市| 新密市| 咸阳市| 遵义县|