c#udp協(xié)議拆包封包_第1頁
c#udp協(xié)議拆包封包_第2頁
c#udp協(xié)議拆包封包_第3頁
c#udp協(xié)議拆包封包_第4頁
c#udp協(xié)議拆包封包_第5頁
已閱讀5頁,還剩3頁未讀 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領

文檔簡介

1、蛙蛙教你解析網(wǎng)絡包摘要:做網(wǎng)絡應用,封包,解包是家常便飯,但如何做到準確、穩(wěn)定而且性能好,卻不太容易做到,這次 和大家分享一下我在解析網(wǎng)絡包上的經(jīng)驗。思路:設計一個網(wǎng)絡協(xié)議,一般都會分包,一個包就相當于一個邏輯上的命令。1、如果我們用udp協(xié)議,省事的多,一次會收到一個完整的包,但UDP不可靠,順序也不能保證,當然像QQ對UDP封裝的很好,模擬了 TCP的可靠性。網(wǎng)上也有一些封裝好的可靠的UDP組件,大家用的話可以找找。關于用什么協(xié)議好這個問題,本貼不討論。2、如果我們用TCP協(xié)議不是長連接,像HTT P (不考慮Keep Alive )那樣,一個連接上只發(fā)送一個包,我們也會很清晰的區(qū) 分出接

2、受到的每一個包。3、還有就是我們還用TCP長連接,但每次發(fā)送固定長度的包,如果要發(fā)送的數(shù)據(jù)長度不夠就用0補齊,如果大于固定長度,就分成兒個發(fā),這個也很簡單實用。4、再有就是一個包有特定的開始和結尾,比如包頭是vbof包尾是veof,我們在可以從頭讀到尾,并把一個一個的包放入隊列,由處理線程去處理。5、再有一種就是每個包有固定長度的header,這個header里包含一個包的長度信息,我們可以先從頭里讀岀長度信息,然后再借著讀這么長的數(shù)據(jù),完了這就是一個包。關于封包的兒種類型我就想到這么多,其中的利弊大家一看便知,我就不忽悠了,本文主要介紹最后一種方式,好多網(wǎng)絡協(xié)議用的都是這種,包括 CMPP協(xié)

3、議,我們自己設計協(xié)議的時候一般不用像CMPP協(xié)議那樣,因為二進制協(xié)議雖然雖然節(jié)省網(wǎng)絡流量,但可讀性不好。出問題,抓個包分析起來太麻煩。我們可以用.net自帶的序列功能把要發(fā)送的類序列化成XML字符串發(fā)送出去,這多好看呀。由于Socket緩沖區(qū)設置及其他的原因,Socket在接受數(shù)據(jù)的時候有時候不能完整的收到一個包,就是你讀出包的長度后,可能不能一次就讀取這么多數(shù)據(jù)。而如果讀個半截兒的包就用UTFSEncoding等來解析,會解析出亂碼的,我們這里用Encoding. UTFS.GetDecoderO來對包進行成塊兒的解析,它就是用來做這種 事情的。下面就來看一下代碼,代碼的注釋很全,演示了一個

4、包從發(fā)到接受、解析的全過程,其中接受的過程沒有一次收全所有的包, 而是收了好兒次,但我們最終還是成功的解析了收到的包。public static voidUnPack 0SBII /I 聲明通過socket發(fā)送的字符串stri ng toSe ndStri ngBySocket =娃娃士大夫 %# %My name is 蛙蛙王子!II 2、轉換成utf-8字節(jié)數(shù)組byte bsinput = EncodingUTF8.GetBytes(toSendStringBySocket);3、計算要發(fā)送的字節(jié)數(shù)組的長度,并寫到第一塊兒字節(jié)數(shù)組的開頭山般協(xié)議設計里都有一個長度的Header,這里就是寫這

5、個HeaderI int inp utBytesCou nt = bsinp utLe ngth;JJ byte bsl =new byte 4 + 3;/4是一個int的長度,3是底一塊字節(jié)數(shù)組除了 Header剩余的大小Buffer. BlockC op y(BitCo nverter. GetBytes(i np utBytesCou nt).0, bs1,0,4):4、把要發(fā)送的字節(jié)數(shù)組拆分成3塊兒發(fā)岀去,因為 socket在接受字節(jié)數(shù)組的時候/也可能半截半截兒的接收,我們就是要模擬這種效果下的拆包,因為第一塊包寫了/ 一個4個字節(jié)的Header,而第一塊字節(jié)數(shù)組長度是 7 ,所以再寫

6、三個字節(jié)長度的數(shù)ILIint offSet =0:4,3);0, bs2. Le ngth);BufferBlockCo py(bsl nput, offSet, bsl,offSet += bslLe ngth -4:”5、寫第二塊兒數(shù)據(jù)byte bs2 =new byte 8;BufferBlockCo py(bsl nput, offSet, bs2,offSet += bs2Le ngth;6寫第三塊兒數(shù)據(jù),我們這里模擬在最后一塊數(shù)據(jù)的末尾加一些亂七八糟的數(shù)據(jù)/這些亂七八糟的數(shù)據(jù)有可能是下一個包的headerbyte bs3 =new byte bs Input .Length - o

7、ffSet +4:i I Buffer. BlockCopy(bslnput, offSet, bs3,0, bsl np ut. Le ngth - offSet);new byte 1 ,2,3,4 ,0, bs3, bs3. Length -4,4);II11 I /7、Socket的接收方在執(zhí)彳丁 BeginReceive函數(shù),并回調函數(shù)里把收到的數(shù)據(jù)放入一個隊列里11 /dotNe t的隊列內(nèi)部就是一個環(huán)形數(shù)組,這里直接就當環(huán)形緩沖區(qū)來用了。LI Queuev byte bufferPool =new Queuev byte ();buffer Po olE nqueue(bsl);

8、buffer Po olE nqueue(bs2);buffer Po olE nqueue(bs3);L: 1/8、初始化一些變量準備解包IIIII /聲明一個字符串緩沖區(qū),大小是你的協(xié)議里規(guī)定的最大的包體長度char chars =new char 256 ;/定義一個UTF-8的Decoder ,它可以成塊的解包,內(nèi)部自動維護解析狀態(tài) LI- / 關于它的使用請參考MSDN或者.net框架設計Decoder d = En cod in gUTF8GetDecoder();一 int charLe n =0: /定義每次解包返回的字符長度int p arseBytesCou nt =0;/

9、定義己解包的字節(jié)數(shù)int Len ghHeader =0;/定義收到包的長度bool n eedReadLe ngthHeader =true ; 是否需要讀取長度的頭byte temp Buffer;/9、當環(huán)形緩沖里有數(shù)據(jù)的時候就一直解析IIwhile(bufferPoolCou nt 0)/10 *讀取數(shù)據(jù)包的長度信息,Len gthHeader/因為第一塊兒包包含長度信息,所以要先讀岀來/讀了長度包后,要把數(shù)據(jù)庫解析偏移量加if (needReadLengthHeader)Len ghHeader = BitC on verterTo In t32 (bsl, p arseBytesC

10、ou n t);n eedReadLe ngthHeader =falsesrcOffSet =4;IH11、從環(huán)形緩沖區(qū)取岀一塊兒數(shù)據(jù)temp Buffer = buffe rPo olDequeueO;/更改己解析p arseBytesCou nt += temp BufferLe ngthsrcOffSet;的字節(jié)數(shù)LLI /i2、如果己解析的字節(jié)數(shù)大于數(shù)據(jù)的長度,那么只解需要解析的字節(jié)IIIif (p arseBytesCou nt Len ghHeader)p arseBytesCou nt 一二 temp BufferLe ngth;dGetChars(te mp Buffer, srcOffSet, inp utBytesCou nt 一 parseBytesCou nt, chars, charLe n);/這里記錄下當前的臨時緩沖區(qū)己解析到了什么位置,準備解析下一個包IIIsrcOffSet = inp utBytesCou nt 一 p arseBytesCoubreak ;/13、解析這半拉包charLe n +二

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論