?重裝TCP數(shù)據(jù)段,我看了《TCP/IP詳解卷二:實(shí)現(xiàn)》覺得它里面的實(shí)現(xiàn)考慮的很全面,當(dāng)然也就很復(fù)雜。而我組裝只是為了監(jiān)視,所以不必那么復(fù)雜,于是自己想了一個(gè)方法。現(xiàn)在我已經(jīng)根據(jù)這個(gè)方法成功組裝TCP分段,所以這個(gè)方法是可行的。另外,我的IP分片的組裝用的方法跟這個(gè)方法也差不多。
??? 首先說下存儲(chǔ)tcp分段的數(shù)據(jù)結(jié)構(gòu):一個(gè)二維鏈表,我把它叫作重裝表。具有相同socket對(duì)(源ip地址、目的ip地址、源端口號(hào)、目的端口號(hào))的tcp數(shù)據(jù)包放在一個(gè)橫向的鏈表里,該鏈表的頭節(jié)點(diǎn)只保存了源ip地址、目的ip地址、源端口號(hào)、目的端口號(hào)這些信息。如下圖所示:
?
??? 然后介紹重裝TCP數(shù)據(jù)段的方法:
1.每到來一個(gè)tcp數(shù)據(jù)包(pkt),我先將該數(shù)據(jù)包的源ip地址、目的ip地址、源端口號(hào)、目的端口號(hào)取出來在重裝表(tpq_tbl)中縱向的鏈表中查找有沒有與它相匹配的鏈表(fp)存在,如果有,就把pkt數(shù)據(jù)包放入與它有相同socket對(duì)的fp鏈中,放入鏈表的時(shí),我先查找pkt的順序號(hào)在鏈表中的適當(dāng)位置,然后才放入;如果沒有,則在tpq_tbl中新創(chuàng)建一個(gè)該類型的鏈表頭節(jié)點(diǎn),然后再將其放入新創(chuàng)建的鏈表中。
2.每當(dāng)在fp中放入一個(gè)tcp數(shù)據(jù)段后,我就檢查fp鏈表中的數(shù)據(jù)段是否已經(jīng)到齊了(判斷方法下面介紹),若到齊,就將個(gè)鏈表中所有數(shù)據(jù)段的數(shù)據(jù)部分拼接到一起,得到應(yīng)用層報(bào)文,然后釋放該鏈表,然后重復(fù)1-2步驟;若沒到齊,直接重復(fù)1-2步驟。
?關(guān)于判斷一個(gè)鏈表中tcp數(shù)據(jù)段是否到齊的方法:
??? 使用的變量說明:
??? count計(jì)數(shù)器,表示當(dāng)前鏈表中的所有tcp數(shù)據(jù)段數(shù)據(jù)部分的長(zhǎng)度之和。每當(dāng)在該鏈表中加入一個(gè)新tcp數(shù)據(jù)段時(shí),我都會(huì)將count累加上該tcp數(shù)據(jù)段的數(shù)據(jù)部分的長(zhǎng)度。
??? syn_seq,表示本次tcp連接的第一個(gè)數(shù)據(jù)包的順序號(hào),也就是建立tcp連接時(shí)的第一次握手的SYN包的順序號(hào)。
??? fin_seq,表示本次tcp連接的最后一個(gè)數(shù)據(jù)包的順序號(hào),也就是關(guān)閉tcp連接時(shí)的第二個(gè)FIN包的順序號(hào)。
??? 判斷:當(dāng)(fin_seq - syn_seq)與count相等時(shí),就說明tcp數(shù)據(jù)段已經(jīng)到齊,否則就是沒有到齊。