首先點一下TCP協議和Socket各個API函數的關系:
服務端只有bind()沒有Listen(),客戶端會Connect()成功嗎?
- Connect()失敗
- bind()操作只是服務端綁定IP:Port(其他進程便無法bind()此IP:Port),並沒有監聽,lsof -i找不到端口對應的Fd
服務端只有Listen()沒有accept(),客戶端會Connect()成功嗎?
- Connect()成功,且tcpdump有完整的3次握手報文
- Listen()操作後,內核會維護一個監聽隊列,用於與客戶端建立連接(完成3次握手),故客戶端能Connect()成功。
服務端accept()會產生網絡通訊嗎?
- 沒有,tcpdump顯示沒有報文產生
- accept()操作只是從Listen()的監聽隊列中取出一個連接,並建立一個新Socket用於與客戶端通訊,故沒有網絡通訊產生。
服務端只有Listen()沒有accept(),客戶端Connect()成功後可以調用write()寫數據嗎?
- 可以寫數據,write()調用返回成功,且tcpdump有完整的請求[PSH]-應答[ACK]報文產生
- 雖然沒有accept(),但客戶端依然能write()數據,這時數據存儲在服務端的TCP緩沖區中,等到進程accept()之後還可以read()到
服務端只有Listen()沒有accept(),客戶端連接能正常斷開嗎?
- 不能,客戶端調用close()之後,tcpdump顯示沒有完整的4次握手斷開報文,只有前2個報文[FIN]和[ACK]
- 由於服務端沒有accept()取出連接fd調用close(),對於服務端沒有調用close()的連接,由上圖可知客戶端的TCP連接會停留在FIN_WAIT_2狀態,一直占用客戶端資源到FIN_WAIT_2狀態超時
- 故Socket編程最後加上close()是必要的編程規范