shutdown()函数:优雅地断开TCP连接
調用 close()/closesocket() 函數意味著完全斷開連接,即不能發送數據也不能接收數據,這種“生硬”的方式有時候會顯得不太“優雅”。
圖1:close()/closesocket() 斷開連接
上圖演示了兩臺正在進行雙向通信的主機。主機A發送完數據后,單方面調用?close()/closesocket() 斷開連接,之后主機A、B都不能再接受對方傳輸的數據。實際上,是完全無法調用與數據收發有關的函數。
一般情況下這不會有問題,但有些特殊時刻,需要只斷開一條數據傳輸通道,而保留另一條。
使用 shutdown() 函數可以達到這個目的,它的原型為:
sock 為需要斷開的套接字,howto 為斷開方式。
howto 在 Linux 下有以下取值:
- SHUT_RD:斷開輸入流。套接字無法接收數據(即使輸入緩沖區收到數據也被抹去),無法調用輸入相關函數。
- SHUT_WR:斷開輸出流。套接字無法發送數據,但如果輸出緩沖區中還有未傳輸的數據,則將傳遞到目標主機。
- SHUT_RDWR:同時斷開 I/O 流。相當于分兩次調用 shutdown(),其中一次以 SHUT_RD 為參數,另一次以 SHUT_WR 為參數。
howto 在 Windows 下有以下取值:
- SD_RECEIVE:關閉接收操作,也就是斷開輸入流。
- SD_SEND:關閉發送操作,也就是斷開輸出流。
- SD_BOTH:同時關閉接收和發送操作。
至于什么時候需要調用 shutdown() 函數,下節我們會以文件傳輸為例進行講解。
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() 不會。
總結
以上是生活随笔為你收集整理的shutdown()函数:优雅地断开TCP连接的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据结构之线性表:单链表
- 下一篇: socket编程实现文件传输功能