調用 close()/closesocket() 函數意味着徹底斷開鏈接,即不能發送數據也不能接收數據,這種「生硬」的方式有時候會顯得不太「優雅」。
上圖演示了兩臺正在進行雙向通訊的主機。主機A發送完數據後,單方面調用 close()/closesocket() 斷開鏈接,以後主機A、B都不能再接受對方傳輸的數據。實際上,是徹底沒法調用與數據收發有關的函數。緩存
通常狀況下這不會有問題,但有些特殊時刻,須要只斷開一條數據傳輸通道,而保留另外一條。
使用 shutdown() 函數能夠達到這個目的,它的原型爲:網絡
int shutdown(int sock, int howto); //Linux int shutdown(SOCKET s, int howto); //Windows
sock 爲須要斷開的套接字,howto 爲斷開方式。socket
howto 在 Linux 下有如下取值:ide
howto 在 Windows 下有如下取值:函數
至於何時須要調用 shutdown() 函數,下節咱們會以文件傳輸爲例進行講解。code
確切地說,close() / closesocket() 用來關閉套接字,將套接字描述符(或句柄)從內存清除,以後不再能使用該套接字,與C語言中的 fclose() 相似。應用程序關閉套接字後,與該套接字相關的鏈接和緩存也失去了意義,TCP協議會自動觸發關閉鏈接的操做。shutdown() 用來關閉鏈接,而不是套接字,無論調用多少次 shutdown(),套接字依然存在,直到調用 close() / closesocket() 將套接字從內存清除。
調用 close()/closesocket() 關閉套接字時,或調用 shutdown() 關閉輸出流時,都會向對方發送 FIN 包。FIN 包表示數據傳輸完畢,計算機收到 FIN 包就知道不會再有數據傳送過來了。
默認狀況下,close()/closesocket() 會當即向網絡中發送FIN包,無論輸出緩衝區中是否還有數據,而shutdown() 會等輸出緩衝區中的數據傳輸完畢再發送FIN包。也就意味着,調用 close()/closesocket() 將丟失輸出緩衝區中的數據,而調用 shutdown() 不會。blog