socket編程-優雅的斷開鏈接shutdown

調用 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

  • SHUT_RD:斷開輸入流。套接字沒法接收數據(即便輸入緩衝區收到數據也被抹去),沒法調用輸入相關函數。
  • SHUT_WR:斷開輸出流。套接字沒法發送數據,但若是輸出緩衝區中還有未傳輸的數據,則將傳遞到目標主機。
  • SHUT_RDWR:同時斷開 I/O 流。至關於分兩次調用 shutdown(),其中一次以 SHUT_RD 爲參數,另外一次以 SHUT_WR 爲參數。

howto 在 Windows 下有如下取值:函數

  • SD_RECEIVE:關閉接收操做,也就是斷開輸入流。
  • SD_SEND:關閉發送操做,也就是斷開輸出流。
  • SD_BOTH:同時關閉接收和發送操做。

至於何時須要調用 shutdown() 函數,下節咱們會以文件傳輸爲例進行講解。code

close()/closesocket()和shutdown()的區別

確切地說,close() / closesocket() 用來關閉套接字,將套接字描述符(或句柄)從內存清除,以後不再能使用該套接字,與C語言中的 fclose() 相似。應用程序關閉套接字後,與該套接字相關的鏈接和緩存也失去了意義,TCP協議會自動觸發關閉鏈接的操做。shutdown() 用來關閉鏈接,而不是套接字,無論調用多少次 shutdown(),套接字依然存在,直到調用 close() / closesocket() 將套接字從內存清除。
調用 close()/closesocket() 關閉套接字時,或調用 shutdown() 關閉輸出流時,都會向對方發送 FIN 包。FIN 包表示數據傳輸完畢,計算機收到 FIN 包就知道不會再有數據傳送過來了。
默認狀況下,close()/closesocket() 會當即向網絡中發送FIN包,無論輸出緩衝區中是否還有數據,而shutdown() 會等輸出緩衝區中的數據傳輸完畢再發送FIN包。也就意味着,調用 close()/closesocket() 將丟失輸出緩衝區中的數據,而調用 shutdown() 不會。blog

相關文章
相關標籤/搜索