connect & send 在三次握手過程中的有趣問題

一、問題回顧

面試的時候被問到的問題,原問題是:

1:寫一下socket網絡編程服務端和客戶端常用的函數。
2:如果服務端在listen之後沒有accept,那客戶端的connect會返回嗎?爲什麼?
3:此時調用send發數據會怎麼樣?

在看下面答案之前,推薦閱讀:
深入探索 Linux listen() 函數 backlog 的含義

Socket accept queue is full 但是一個連接需要從SYN->ACCEPT

下面是我對這個問題實驗整理的結果:

情況 ESTABLISHED 隊列沒有滿 SYN_RECV隊列沒有滿 SYN_RECV 隊列滿了
connect返回情況 connect 正常返回 connect 正常返回 connect返回timeout錯誤
send寫數據 完全正常寫,並且數據會被服務器回覆ack確認。之後如果accept,可以read出數據。 不能正常發送,會不斷觸發重傳,但是數據不會被確認。 這時候的socket是完全disconnect的,send給disconnect的socket寫數據,觸發SIGPIPE信號,默認殺死本進程。

二、總結

有關connect函數返回錯誤的情況,常見的有下面三種:

  • 返回TIMEOUT,即SYN_RECV隊列都滿了,對於客戶端發來的三次握手第一次的SYN都沒有辦法響應,這時候TCP會隔6s24s重發,直到75s,如果還是沒有被接受,最後返回TIMEOUT錯誤。
  • 返回ECONNREFUSED錯誤,表示服務器主機沒有在相應的端口開啓監聽。
  • 返回EHOSTUNREACHENETUNREACH,表示在某個中間路由節點返回了ICMP錯誤,這個錯誤被內核先保存,之後繼續按照6s24s重發,直到75s,如果還是沒有響應,就返回EHOSTUNREACHENETUNREACH錯誤。

我那個問題只涉及了TIMEOUT的情況,沒有後兩種,另外:

connect什麼時候正常返回?

其實是客戶端收到服務器三次握手第二次返回的SYN+ACK之後,自己進入了ESTABLISHED狀態(TCP狀態轉換圖),這時候connect就會正常返回了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章