用mina做基於tcp,udp有通訊有段時間了,一直對編碼解碼不是很熟悉,這次做項目的時候碰到了斷包情況,貼一下解決過程,
我接受數據格式如下圖所示:
unit32為c++中數據類型,代表4個字節,由上圖可以看出第二個參數為數據長度
protected boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception { in.order(ByteOrder.LITTLE_ENDIAN);//c++中默認讀取數據是這個模式 int remaining = in.remaining(); if (remaining > 0) { in.mark();// 標記當前位置,以便reset int head = in.getInt();//消息頭對應上圖0x0 int length = in.getInt();//數據長度 if (length > remaining) {// 如果消息內容不夠,則重置,相當於不讀取size System.out.println("斷包了, left=" + in.remaining()+ " length=" + length); in.reset(); return false;// 接收新數據,以拼湊成完整數據 此時斷掉的前半部分數據仍在緩沖區中等待讀取 } else {//數據完整,封住新的IoBuffer中傳給messageReceived方法處理 byte[] bytes = new byte[length - 8];//獲取數據長度時已經讀取了八個字節,在這里去掉 in.get(bytes); IoBuffer buffer = IoBuffer.allocate(length); buffer.putInt(head); //把剛才讀取到的數據重新放入buffer中 buffer.putInt(length); buffer.put(bytes); buffer.flip(); out.write(buffer); if (in.remaining() > 0) {// 如果讀取內容后還粘了包,就讓父類再給一次,進行下一次解析 // System.out.println("package left="+in.remaining()+" data="+in.toString()); } return true;// 這里有兩種情況1:沒數據了,那么就結束當前調用,有數據就再次調用 } } return false;// 處理成功,讓父類進行接收下個包 }
中間遇到各種坑,總的來說還是對IoBuffer和mina框架的理解不夠深入,記錄下引以為戒........