用Wireshark分析Socket連接建立的過程


0. 安裝Wireshark,但是默認情況下,Wireshark無法捕獲127.0.0.1的報文

解決方案:安裝npcap,替換默認的winpacp,重新啟動Wireshark,就可以看到一個名字中含有Loopback的接口,針對它來抓包就行了

 

1. 用telnet向未被監聽的9090端口發送連接請求

telnet窗口一閃而過,抓包結果如下

可以看出,未被監聽的端口會直接返回RST包,導致Telnet無法正常建立連接。

 

2. 開啟echo server監聽9090端口,然后使用telent向9090端口發送連接請求

可以清楚的看到TCP的三次握手過程,現在Telnet已經與echo server建立了TCP連接了

 

3. 在第二步的基礎上,使用telenet向echo server發送數據

我在Telnet里輸入了abc三個字符,下圖是抓包結果

可以看到一共有12個包,每四個包為一組,對應於Telnet中的一次輸入

這四個包分別對應於 客戶端發送字符->服務器ack->服務器發送echo->客戶端ack

 

4. 在BIO模式的echo server中插入斷點

使用BIO模式的echo server,但是在調用ServerSocket.accept()方法處下斷點,讓程序跑到此處停頓。

然后啟動Telnet向服務器發送數據,結果如下:

可以看到在這種情況下,居然可以完成三次握手協議,正常建立連接(但此時服務端正卡在accept()方法上)

對於客戶端后續發送的數據,服務端也能及時發送ack,只是無法發送echo罷了。一旦放開echo server的斷點,服務器就能正常工作了,前面沒收到echo的數據也不會丟失。

 

5. 在NIO模式的echo server中插入斷點

與BIO模式相近,ServerSocketChannel只要與端口綁定,對於Telnet的連接請求,無需服務端調用accept方法就能完成三次握手。

客戶端后續發送的數據,服務端也能正常返回ack。

 

6. 為什么只需要完成監聽端口,無需調用accept方法就能完成三次握手呢?

我之前的想法是:accept方法在收到客戶端發過來的syn包后就會從阻塞狀態中退出,在此同時返回ack+syn包,完成三次握手(這個想法太奇怪了)

實際上是tcp底層維護了兩個隊列:半連接隊列與全連接隊列。操作系統收到Telnet的tcp連接請求后會自動完成三次握手建立TCP連接,然后將這個連接放到全連接隊列中。而accept方法則是將TCP連接從這個全連接隊列中提取出來罷了。

簡單測試一下,在創建ServerSocket對象的時候,將backlog設置為1,然后將斷點設置在accept方法處(不讓程序從TCP全連接隊列中提取連接)。然后開啟兩個Telnet客戶端,結果第一個Telnet可以正常連接,第二個Telnet直接閃退了。

抓包如下圖所示:

可以清楚的看到從6078到9090的TCP連接成功的完成了三次握手,從6079到9090的TCP連接則握手失敗了。

 

參考資料:

關於TCP 半連接隊列和全連接隊列


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM