程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> DIOCP開源項目-詳解編碼器和解碼器和如何在傳輸中加入壓縮和解壓功能

DIOCP開源項目-詳解編碼器和解碼器和如何在傳輸中加入壓縮和解壓功能

編輯:Delphi

>>>>>>DIOCP討論群:320641073

>>>>>>SVN源碼和DEMO下載:https://code.google.com/p/diocp/

網絡帶寬有限,對數據進行壓縮再進行傳送可以有效的利用帶寬和提高傳輸的效率。

DIOCP中對數據進行壓縮傳送,需要修改編碼器和解碼器,先說說這兩個東西的的用法和功能。

      

         

         

          在之前編寫的DIOCP例子中都使用了JSonStream對象進行傳輸,這個TJSonStream類,主要有兩個部分的數據,第一部分包含JSon字符串數據,第二部分包含Stream流數據。在三層數據保存例子中我們把客戶端的請求放在JSon中。服務端接收數據後通過服務端的解碼器還原成JSonStream對象。然後進行邏輯的處理,服務端回寫對象時,同過服務端的編碼器對回寫的JSonStream進行編碼發送,客戶端通過客戶端的解碼器接收並還原成JSonStream對象。在服務端回寫CDS數據包時將xml字符串數據寫在JSonStream.Stream中,如果對Stream對象進行壓縮,在做壓縮中調試程序時發現一個70K的數據包進行一下壓縮,數據包可以變成7K了,對文本壓縮效果還是很不錯的。

       

        下面分析下代碼

客戶端代碼:

==] := ;   //] :=;

首先是建立一個TJSonStream對象,然後設定信息,因為是發生SQL所以沒有Stream數據。後面是用FClientSocket.sendObject(lvJSonStream);//用Socket進行發送,

   FCoder =    Exception.Create(  Active ;

可以看出這裡調用注冊的編碼器,調用Encode函數

 

客戶端編碼器的Encode函數如下

[..] 
   pvObject =  =// (lvJSonStream.Stream <> ) 
  
     lvJSonStream.Json.O[] <>  
    
       lvJSonStream.Json.B[] 
      
        //   lvJSonStream.Stream.Size >  
    
      //] :====== pvSocket.sendBuffer(@lvJSonLength, SizeOf(lvJSonLength)) = SOCKET_ERROR  lvStream <>  
  = 
  = = pvSocket.sendBuffer(@lvStreamLength, SizeOf(lvStreamLength)) = SOCKET_ERROR // pvSocket.sendBuffer(@lvBytes[], Length(lvBytes)) = SOCKET_ERROR  lvStream.Size >  
  = = pvSocket.sendBuffer(@lvBufBytes[], l) = SOCKET_ERROR  (l = ;

該部分完成的功能有

1.判斷Stream數據是否需要壓縮。

2.發送Json數據長度和Stream數據長度

3.發送Json數據

4.發送Stream數據

 

說明:

lvJSonLength := TNetworkTools.ntohl(lvJSonLength);
lvStreamLength := TNetworkTools.ntohl(lvStreamLength);

lvData := TNetworkTools.Utf8Bytes2AnsiString(lvBytes);

這三行代碼需要說明下,是為了兼容java,netty做服務端方便解碼,當然我們也可以不進行轉換。直接發送也是可以的。只要配合服務端就行了。協議是自己定義的。

 

接下來是服務端IOCP隊列中會收到接收數據的信號。

=//= lvIOData.IO_TYPE = IO_TYPE_Accept   //   lvIOData.IO_TYPE = IO_TYPE_Recv 
    
      ////;

 

//加入到套接字對應的緩存中,處理邏輯
lvClientContext.RecvBuffer(lvIOData.DataBuf.buf,
  lvIOData.Overlapped.InternalHigh);

//這裡會調用解碼器嘗試進行解碼

    ////調用注冊的解碼器<進行解碼>= lvObject <>  
    
      
        //
         +//清理掉這一次分配的內存<如果沒有可用的內存塊> FBuffers.validCount =  
      ;

 

我們在之前的Demo中使用的是TIOCPJSonStreamDecoder解碼器

 

 TIOCPJSonStreamDecoder.Decode( = //如果緩存中的數據長度不夠包頭長度,解碼失敗<json字符串長度,流長度>= (lvValidCount < SizeOf(Integer) + SizeOf(Integer)) 
  //==//如果緩存中的數據不夠json的長度和流長度<說明數據還沒有收取完畢>= lvValidCount < (lvJSonLength + lvStreamLength) 
  
    //   (lvJSonLength + lvStreamLength) =  
  
    //兩個都為0<兩個0>//==// lvJSonLength >  
  == 
  , // lvStreamLength >  
  = // lvJsonStream.Json.B[] 
      
        //;

//服務端解碼器中有三行代碼來配合客戶端的編碼流


lvJSonLength := TNetworkTools.ntohl(lvJSonLength);
lvStreamLength := TNetworkTools.ntohl(lvStreamLength);   
lvData := TNetworkTools.Utf8Bytes2AnsiString(lvBytes);

/////

服務端解碼器主要完成的功能有

0.判斷接收到的數據是否可以進行解碼,如果不可以退出,解碼不成功。

1.接收json長度,流數據長度

2.接收json數據,接收流數據存入JsonStream.json中,

3.根據json中config.stream.zip進行判斷流數據是否需要解壓.放入JsonStream.stream中
4.解碼成功返回JsonStream對象。

 

解碼完成後可以看到

=

lvObject <>

//

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved