91av视频/亚洲h视频/操亚洲美女/外国一级黄色毛片 - 国产三级三级三级三级

  • 大小: 0.41M
    文件類型: .pdf
    金幣: 1
    下載: 0 次
    發布日期: 2021-03-27
  • 語言: 其他
  • 標簽: 其他??

資源簡介


本文主要介紹了網絡協議的拆包與封包過程,如:rtp,udp等等協議的拆包與封包,不管是什么協議原理都是一樣的,如果深入掌握了其中的一個,那么在以后網絡協議方面的分析就變得更加得心應手了。從中介紹了大小端問題以及位段操作等等。
網終協議的封包與拆包方法 BitFEDCBA9876513210 -------MSB LSB- Wa110001011|10001010 Ox8A Ox8B 因此、現在就存在個如何處理網絡字節序的問題?稍微處理不正確那么就會出現錯誤, 如上面的0x0800很有可能處理成0x0008了。 位段 信息的存取一般以字節為單位,如上所示,如果是一個字節那么就不存在字節序,即大 小端問題。而實際上,我們有時候存儲個信息不必要用個或者多個字節序,例如:“真” 或“假”用0或1表小,只需要1位即可。因此,以下就來看看在一個byte中如何處理不 同的bit,這在網絡協議中應用是非常廣的。如RTP協議就存在著不同的bit代碼不同的意 思,那么我們應該如何處理這些bit呢? 0 01234567890123456789012345678901 =2Px CC MFI sequence number timestamp synchronization source (SSRC) identifier contributing source (CSRc) identifiers 處理一個字節的不同bit有以下兩種方法: 第一、人為的將一個byte變量data分為幾部分 如讀取data的第4biL的C操作方法data(0x1<4),此種操作方法是不是在單片機操 作中很熟悉呢?我們在操作某位gpio口的時候就經常采用此和方法 第二、利用位段 C語言允許在一個結構體中以位為單位來指定其成員所占內存的長度,這種以位為單位 的成員稱為“位段”或稱為“位域”( bit field)。利用位段能夠用較少的位數存儲數據 如 packed-data所示 struct packed-data unsigned a unsigned b: 6 unsigned C: 4 unsigned d: 4 int 1: i data C y人人 32 第3頁/共10頁 網終協議的封包與拆包方法 因此,接下來你或許會發現以下一個問題,在位段中仍然存在著字節序的問題,如下:0x8B 大端 小 01234567 76543210 MSB- MSB--- LSB 10001010 10001010 Ox8B 所為,我們發現,如果同一byte里面區分了不同的bit的時候,此時就會存在大小端問題 此時,我們用位段去處理的時候只需要記住以卜要點:如果本地的內存存儲方式是小端格 式,那么在處理大端格式的時候就需要人為的將位段處理結構體變化成大端格式;如果本 地的內存存儲是大端格式,那么無需變化。 、協議的封包與拆包 我們在了解了上面的基礎知識以后,或許還不是特別理解,并且我們會考慮如何應用到 實際情況昵?卜面我們通過例舉實際情況以加深理解 例子1、UDP協議的拆包 首先、 google輸入 udp rfc,可以查看到UDP的 header format,如下所示: 78 1516 232431 Source Destination Port + + Leng th Checksum 可以看出udp的四部分: Source port, Dest port, Length以及 Checksum都是占用了 兩個字節,因此,存在著字節序的問題。下面對其進行封裝,如下所示: typedef struct Udplleader Tag unsigned short m nSrcPort unsigned short m nDs tPort unsigned short m nLen unsigned short m nCrc J UdpHeade 我們用 wireshark抓包一個udp的包,如下所示 頁/共10頁 網終協議的封包與拆包方法 E User Datagr am Protocol, src Port: domain (53), Dst Port: 59161 (59161 Source port: domain (53> Destination port: 59161 (59161) Leng g Checksum: 0x02d5 varication disabled] d checksum: Falsel Bad checksum: False」 0000b870f403fc120C02a5420058864110c 0.,d 00100412006900245000067000000004011...1·!E..g..· 00201feca6086210a000070035719009…:·!·5 3031036e65740050010001c00c0c 00500100010c00003c0004b4a913aoc00c0c 00600100010c00003c0004b4a91483c00c0c 00700100010C00003c0004b4a914tb 從中可以看出, source port是53, destination port是59161, lenth是83, checksum 是0x02d5,然后,我們通過接收處理到的 buffer值會是0x00,0x35,0xe7,0x19,0x00,0x53, x02,0xd5,那么我們如何處理這些值?從而止確的分析udp頭呢?在程序測試之前,我們 首先來分析內存情況。 如果本地是小端模式,如x86、am系列處理器,那么 buffer在內存中的分布如下 LoW 0x00 src low rc high 0x35 dst low dst high Oxen Tem len h x19 crc 1 crc h 0x00 x53 0x02 High Oxd5 左邊為 buffer內存分布示意圖,右邊為 UdpHeader內存示意圖 因此、如 source port在 buffer中存儲的大端模式是0x00,0x35,但是到了小端處理器(x86、arm 進行處理的時佚,就會出現 UdpHeader中的 src port為0x3500現象,因此,與實際的 source port為53 完仝不同。測試結果如下所示 c0t35(13568) dest port 19e7(6631> len port 5300(21248> rc port d552(54530> 測試代碼: 第5頁/共10頁 網終協議的封包與拆包方法 typedef struct UdpHeaderTag short m nsi unsigned short m nDstPort d short m nl unsigned short m nCrc J UdpHeader int main (int argc, char *argyI char buffer-{0x00,0x35,0xe7,0x19,0x00,0x53,0x02,0xd5}; UdpHeader =kpUdpHeader =(UdpHeader **)buffer printf( src port %04x(%cd)\n", pLdplleader->m nSrcPort, pUdplleader->m nSrcPort printf( dest port %04x (%d)n", pUdpHeader->m nDstPort, pUdpHeader->m n Ds tPort) printf( len port %04x(ocd)\n, pUdpHcader->m nLen, pUdpHcader->m nLen printf(crc port %04x(cd)\n, pUdpHeader->m nCre, pUdpHeader->m nCrc) 但是,如果將上述代碼運行在大端處理器( powerpc),則不會出現以上現象,原因如下 LOW 0x00 Src_high src low 0x35 dst high dst lot Oxel Ten en crc h Crc x19 x00 x53 0x02 High 左邊為 buffer內存分布示意圖,右邊為 UdpHeader內存示意圖 因此、當在小端模式(x86、arm)處理器上處理網絡協議的時候,則需要注意字節序的問題 如以上修改為如下格式即可了正確解析 udp header了。 #include <stdio. h> #inc lude <winsock. hy 頁/共10頁 網終協議的封包與拆包方法 typedef struct UdpHeaderTag short m nsi unsigned short m nDstPort unsigned short m nLen gned short m nC J UdpHeader char*argv「 bufferLl-0x00, 0x35 0 UdpHeader =kpUdpHeader =(UdpHeader **)buffer printf("轉換前:n"); printf ("src port %04x(ocd)\n, pUdpHcader->m nSrcPort, pUdpHcadcr->m nSrc Port printf( dest port %04x(%d)\n", pUdpHeader-m nDst Port, pUdpHeader->m nDs tOrt) printf(" len port %01x(o%cd)\n, pUdpHeader->m nLen, pUdpHeader->m nLen) printf(crc port %04x(%d)\n", pl. dpHeader->m nCrc, pl dpHeader->m nCrc printf("轉換后:\n") printf pUdpHeader->m nSrcPort ntohs(pUdpHeader->m nSrcPort) pUdpHeader->m nlst Port = ntohs(pUdpHeader->m nDstl'ort) pUdpHeader->m nLen ntohs(pUdpHeader->m nLen pUdpHcador->m nCrc-ntohs(pUdpHcadcr->m nCrc) printf( src port %04x(%d)\n, pLdplleader->m nSrcPort, pUdplleader->m nSrc Port) printf("dest port %04x(%d)\n", pUdpHeader->m nDstPort, pUdpHeader->m nDs tPort) printf(len port 9004x(%d)n, pl. dpHeader->m nLen, pU dpHeader->m nL. en) printf( cre port %04x(%d)\n", pUdpHeader->m nCrc, pUdpHeader->m nCrc 協議的封包,同樣以 udp header封包為例,如上我們知道了 source port是53, destination port是59161, lenth是83, checksum是0x02d5,然后我們如何封包成網終 碼流發送出去呢? 通過了以上對網絡數據的拆包詳細了解以后,我們知道如果在小端處理器處理接收到的 網絡數據,那么則需要將網絡數據的網絡格式轉換成本地格式,即 ntohs、 nohl,那么同 樣,如果在小端處理器上發送數據到網絡上,那么,則需要首先將本地的數據格式轉換成網 終數據格式,即 hons、 htonl,因此,封包過程請讀者進行相應測試。 以上都是介紹的是大于一個byte的寧節序問題,可是我們往往一個字節內也分成了不 同的功能作用,而從基礎知識中我們發現了如果一個字節內也區分了不同的功能模塊,那么 也會存在著字節序的問題。 第7頁/共10頁 網終協議的封包與拆包方法 例如: NALU Header由三部分組成,如下所示 0112134|567 -+-+-+-+-+-+-+- IF NRI Type 如果,此時該項為0x7C,那么你知道其中F、NRI、Type分別為多少么?其實,大端模 式如上面提到的是最直觀的字節序,如卜所示: 0123|4|567 -+-+-+-+-+-+-+- F NRI Type 01111100 因此、其中F為0,NRI為3,Type為0xlc(28),可以我們如何用代碼進行區分呢? 此處,就需要用到前面提到的位段模式∫。我們通過位段定了∫NALU結構體,如下所小: typedef struct NALUHcaderTag unsigned char F: 1 unsigned char NrI unsigned char TYPE: 5 LNALUHcadcr 因此,我們編寫了如下測試代碼,解析 typedef struct NALUHeader ta unsigned char F unsigned char NRI: 2 unsigned char TYle: 5 I NALUHeader int main (int argc, char argv []) unsigned char nal=0x7c: NALUHeader *pnal=(NALUHeader *)&nal printf(F: %d\n", pnal->F) printf( Nri: %d\n, pnal->NRI) printf( TYPe: %d\n, pnal->TYPD) 運行結果如下 頁/共10頁 網終協議的封包與拆包方法 F:0 NRI: 2 TYPE: 15 我們發現這似乎并不是我們想要的結果?問題出現在哪兒呢? 我們仍然采用前面的方法進行分析,分別繪制出內存分布圖,如下所示 011 1100 NRI F 個 L 因此、我們現在就不難發現其中的問題了,此處也是存在著一個對應關系,正如前面我 們處理的方式是進行了轉換,即將在小端CPU上處理網絡數據的時候,將網絡數據轉換到本 地的小端格式冉進行處理,如果在小端CP上發送數據到網絡上的時候,那么只需要將本地 的小端數據轉換成網終格式,即大端格式。 那么,此處我們是否仍然可以采用同樣的方法進行呢?然而,我們發現其中的困難了, 其一,以上格式如果進行轉換,那么運算起來比較復雜,并且沒有標準的轉換函數;其二, 以上只是一種bit順序,如果變化了呢?因此,以下提出一種方法進行處理 我們知道κ絡數據是大端格式,那么我們在小端CPU上能否使用大端方式杓造位段結構 體呢?內存分布如下所示: 01111100 NRI丬TYPE H 轉換成C格式如下 typedef struct NALUheadertag unsigned char TYPE: 5; unsigned char unsigned char F: 1 3 NALUHeader 運行結果如下: NRI: 3 TYPE: 28 三、總結 第9頁/共10頁 網終協議的封包與拆包方法 通過以上的分析、學習,我相信在以后的網終協議的分析過程中,基本上不會有在什么 大問題。有的只是需要耐心的理清楚整個內存的分部情況。下面總結以下幾點 1、什么時候存在字節序問題? 由兩個及兩個以上字節組成的選項,則在網終傳輸,CPU處理的時候存在字節序問題? 參考 UDP Header實例 個字節里面區分了不同的bit位的時候,則存在字節序問題,參考 NAL Header實 例; 2、什么時候需耍處理字節序問題? 記住網終傳輸采用大端模式,如果處理數據的CPU是小端模式(x86、arm),那么需要 處埋宇節序問題。如果處理數據CPU是大端模式( powerpc),那么不存在宇節序問題。 當需要處理字節序問題時,有以下兩種方法: 第 處理兩個或者四個字節組成的近項時,采用 tons、 nohl、 hons已經 htonl 進行轉換。 第二、處理一個字節內的選項時,則采用位段結構體,即將位段結構體定義為人端 格式 致讀者 如果您覺得本文的哪些地方需要改進或是存在一些不明白的地方,請點擊這里并留言。 修訂歷史 修訂說明 2013-08-24 新增文檔 0頁/共10頁

資源截圖

代碼片段和文件信息

評論

共有 條評論