>>>>>>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 <>
//