調用 close()/closesocket() 函數意味著完全斷開連接澈灼,即不能發(fā)送數據也不能接收數據,這種“生硬”的方式有時候會顯得不太“優(yōu)雅”序攘。
上圖演示了兩臺正在進行雙向通信的主機抱婉。主機A發(fā)送完數據后,單方面調用 close()/closesocket() 斷開連接瓶佳,之后主機A芋膘、B都不能再接受對方傳輸的數據。實際上霸饲,是完全無法調用與數據收發(fā)有關的函數为朋。
一般情況下這不會有問題,但有些特殊時刻贴彼,需要只斷開一條數據傳輸通道潜腻,而保留另一條。
使用 shutdown() 函數可以達到這個目的器仗,它的原型為:
int shutdown(int sock, int howto); //Linux
int shutdown(SOCKET s, int howto); //Windows
sock 為需要斷開的套接字融涣,howto 為斷開方式童番。
howto 在 Linux 下有以下取值:
- SHUT_RD:斷開輸入流。套接字無法接收數據(即使輸入緩沖區(qū)收到數據也被抹去)威鹿,無法調用輸入相關函數剃斧。
- SHUT_WR:斷開輸出流。套接字無法發(fā)送數據忽你,但如果輸出緩沖區(qū)中還有未傳輸的數據幼东,則將傳遞到目標主機。
- SHUT_RDWR:同時斷開 I/O 流科雳。相當于分兩次調用 shutdown()根蟹,其中一次以 SHUT_RD 為參數,另一次以 SHUT_WR 為參數糟秘。
howto 在 Windows 下有以下取值:
- SD_RECEIVE:關閉接收操作简逮,也就是斷開輸入流。
- SD_SEND:關閉發(fā)送操作尿赚,也就是斷開輸出流散庶。
- SD_BOTH:同時關閉接收和發(fā)送操作。
至于什么時候需要調用 shutdown() 函數凌净,下節(jié)我們會以文件傳輸為例進行講解悲龟。
close()/closesocket()和shutdown()的區(qū)別##
確切地說,close() / closesocket() 用來關閉套接字冰寻,將套接字描述符(或句柄)從內存清除须教,之后再也不能使用該套接字,與C語言中的 fclose() 類似性雄。應用程序關閉套接字后没卸,與該套接字相關的連接和緩存也失去了意義羹奉,TCP協議會自動觸發(fā)關閉連接的操作秒旋。
shutdown() 用來關閉連接,而不是套接字诀拭,不管調用多少次 shutdown()迁筛,套接字依然存在,直到調用 close() / closesocket() 將套接字從內存清除耕挨。
調用 close()/closesocket() 關閉套接字時细卧,或調用 shutdown() 關閉輸出流時,都會向對方發(fā)送 FIN 包筒占。FIN 包表示數據傳輸完畢贪庙,計算機收到 FIN 包就知道不會再有數據傳送過來了。
默認情況下翰苫,close()/closesocket() 會立即向網絡中發(fā)送FIN包止邮,不管輸出緩沖區(qū)中是否還有數據这橙,而shutdown() 會等輸出緩沖區(qū)中的數據傳輸完畢再發(fā)送FIN包。也就意味著导披,調用 close()/closesocket() 將丟失輸出緩沖區(qū)中的數據屈扎,而調用 shutdown() 不會。