在此MSDN頁:爲什麼要在關閉套接字之前使用shutdown()?
Sending and Receiving Data on the Client
它建議關閉套接字的發送方使用:
shutdown(SOCK_ID, SD_SEND);
爲什麼要這樣呢?
也許我不就得了,它只是一個建議?也許是爲了節省內存?也許速度?
有沒有人有想法?
在此MSDN頁:爲什麼要在關閉套接字之前使用shutdown()?
Sending and Receiving Data on the Client
它建議關閉套接字的發送方使用:
shutdown(SOCK_ID, SD_SEND);
爲什麼要這樣呢?
也許我不就得了,它只是一個建議?也許是爲了節省內存?也許速度?
有沒有人有想法?
答案是shutdown()
文檔中:
如果該參數是如何
SD_SEND
,隨後到send
函數調用是不允許的。 對於TCP套接字,所有數據被髮送和確認由接收後FIN
將被髮送。...
,以確保所有數據的發送和在關閉之前在一個連接的插座接受,應用程序應該使用
shutdown
調用closesocket
之前關閉連接。一種方法來等待遠端已經發送的所有數據,併發起了一個優美的斷開通知使用WSAEventSelect
功能如下:
- 呼叫
WSAEventSelect
爲FD_CLOSE
註冊通知。- 呼叫
shutdown
與how=SD_SEND
。- 當接收
FD_CLOSE
,調用recv
或WSARecv
直到函數成功完成,並且指示收到零個字節。如果SOCKET_ERROR
已返回,則無法正常斷開連接。- 呼叫
closesocket
。另一種方法來等待遠端已經發送的所有數據,併發起了一個優美的脫節用途通知重疊接聽電話如下:
- 呼叫
shutdown
與how=SD_SEND
。- 呼叫
recv
或WSARecv
直到函數成功完成,並表示收到零個字節。如果SOCKET_ERROR
已返回,則無法正常斷開連接。- 呼叫
closesocket
。...
欲瞭解更多信息,請參閱Graceful Shutdown, Linger Options, and Socket Closure部分。
換句話說,至少對於TCP,調用shutdown(SD_SEND)
通知你完成發送更多的數據同行,那你可能會很快結束你的連接端。最好,同行也會爲你做同樣的禮貌。這樣,兩個同伴都可以知道兩端故意關閉連接。這被稱爲曼妙斷開連接,而不是一個流產或異常斷開連接。
默認情況下,如果你不叫shutdown(SD_SEND)
,closesocket()
將嘗試爲您執行正常關機除非插座的linger選項被禁用。最好不要依賴這種行爲,除非你有充分的理由,否則在致電closesocket()
之前,你應該總是自己打電話shutdown()
。
實際上,'closesocket'只會在你關閉連接的最後一個引用時執行。如果你試圖關閉連接,只調用'shutdown'就可以保證你做到了,並且知道它是否工作。 'closesocket'函數可能會成功,對連接什麼都不做。 –
@DavidSchwartz:我假設你指的是通過使用['WSADuplicateSocket()'](https://msdn.microsoft.com/en-us/library/windows/desktop/ms741565.aspx) ?否則,我不知道你的意思。 –
除非逗留是*啓用*零超時,*或*您的套接字接收緩衝區中有未讀數據。這種同步關閉的情況相當專業化,本身並不是一個足以推薦'shutdown()'的普遍理由。我從來沒有用過它。 – EJP
有與發送或插座上接收操作相關聯的特定資源,插座要麼使用或關閉。有關閉的原因與資源管理無關。關閉套接字是實現所謂的優雅關閉協議,它允許通信雙方實現連接正在關閉並允許最小化數據丟失。
這是不必要的和多餘的,除了下列情況:
這是我所見過的大約30年跨越的唯一案例:有可能是別人,但我不知道他們。
難道你幾乎總是想實現同步關閉?我不知道我遇到過不想同步關閉的情況。如果在拆解過程中發生錯誤,您想記錄錯誤的情況如何?你的回答讓95%的情況聽起來像是個例外! –
@DavidSchwartz不,我並不總是想實現同步關閉。我懷疑在25年的網絡編程中,我曾經編碼過一個,甚至看過一個。 HTTP是地球上最常用的應用協議,它不使用它。 TLS也沒有。我還沒有研究過任何其他應用協議。 – EJP
如果您無法在Windows上執行操作,如何幹淨地關閉HTTP連接並記錄錯誤?你可以調用'closesocket'並且沒有錯誤,並且不能保證連接完全關閉。 –
它*可能會釋放一些用於發送的資源?至少套接字描述符本身將被釋放。但我並沒有真正看到它的理由,而不是你鏈接到的程序。 –
您的問題包含一個常見但嚴重的混淆。你說「它建議關閉socket的發送端」。不,不是的。套接字沒有邊。它建議關閉socket指向的* connection *的發送端。一旦你意識到這種差異有多重要,你會發現你別無選擇。 'closesocket'函數是套接字上的操作,而不是連接。如果你想正常關閉連接,你有什麼選擇? –
@Someprogrammerdude套接字描述符本身肯定不會被釋放。否則,以下關閉(a)不可能工作,(b)將是毫無意義的,但事實並非如此。 – EJP