mina IoBuffer 處理斷包、粘包




  今天下午重溫了一下項目中消息處理部分,其中關於IoBuffer重新學習了一下。

  版本mina1.7.;

  IoBuffer中有三個重要的方法,limit capacity position.

  其中capacity >= limit >= position >= 0;

  在mina1.7版本中IoBuffer還不支持自動增長,所以在接收數據的時候,必須手動擴展其容量。

  private DEFAULT_CAPACITY = 64;

private IoBuffer buffer = IoBuffer.allocate(DEFAULT_CAPACITY);

private void decode(IoBuffer in) {
 put(in); // 添加新數據 
}


private void put(IoBuffer in) {
   // 將要添加的數據超過預定義的容量大小
   if (in.remaining > buffer.remaining()) {
      // 擴大空間的1.5倍
      expend((buffer.position() + in.remianing)) * 3 / 2);       
   }
}

private void expend(int capacity) {
  IoBuffer newBuffer = IoBuffer.allocate(capacity);
  buffer.flip();
  newBuffer.put(buffer);
  buffer = newBuffer;
}

  這樣我們就實現了IoBuffer的空間擴展。

  

  在接收客戶端數據的時候,有三種情況出現:1)正常數據包 2)斷包,也就是數據不全 3)粘包,多個包數據情況

 

  在正常數據包的情況下,我們正常處理即可。

  在斷包時,我們就要保存上一次發送過來的數據,以便在下一次數據過來時,可以連接的上。

  

  例如:將2個Buffer數據合爲1個

  IoBuffer totalData = IoBuffer.allocate(20);
  IoBuffer buf1 = IoBuffer.allocate(8);
  IoBuffer buf2 = IoBuffer.allocate(8);
  完整數據爲1、2、3、4;
  buf1.putInt(1);
  buf1.putInt(2);
  buf1.flip();
  totalData.put(buf1.buf()); // 這樣我們將buf1中的數據存放到了totalData中。但是並不是完整的數據,所以我們還需要再接收buf2的數據。
  totalData.flip();
  在讀取數據之前,我們記下totalData的limit
  int limit = totalData.limit();
  先讀出2個數據。totalData.getInt();totalData.getInt();
  此時totalData.position() 爲8;totalData.limit()爲8;
  因爲數據不完整,所以在有數據過來時,我們要從position = 8這個位置開始讀取新的數據。
  所以我們這是position的起點爲剛開始記錄的limit
  totalData.position(limit); 這樣再數據過來時,就從limit位置開始存儲新數據
 
  totalData.put(buf2.buf());
  totalData.flip(); 這樣就把buf1和buf2的數據全部都合併起來了,也就是我們處理斷包和粘包時候的操作。


 

  這裏只是寫了一個囉嗦繁瑣的實例,讓過程看的更清晰,真實世界中,我們會在循環不斷的去讀取數據。


發佈了180 篇原創文章 · 獲贊 52 · 訪問量 92萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章