linux socket close返回,Linux-socket的close和shutdown區別及應用場景

shutdown的定義

#include

int shutdown(int sockfd,int how);

how的方式有三種分別是:

SHUT_RD(0):關閉sockfd上的讀功能,此選項將不允許sockfd進行讀操作。即該套接字不再接受數據,任何當前在套接字接受緩沖區的數據將被丟棄。進程將不能對該套接字發出任何讀操作。對TCP套接字該調用之后接受到的任何數據將被確認然后無聲的丟棄掉。

SHUT_WR(1):關閉sockfd的寫功能,此選項將不允許sockfd進行寫操作,即進程不能在對此套接字發出寫操作。

SHUT_RDWR(2):關閉sockfd的讀寫功能,相當於調用shutdown兩次:首先是以SHUT_RD,然后以SHUT_WR。

成功則返回0,錯誤返回-1,錯誤碼errno:EBADF表示sockfd不是一個有效描述符;ENOTCONN表示sockfd未連接;ENOTSOCK表示sockfd是一個文件描述符而不是socket描述符。

shutdown()的效果是累計的,不可逆轉的。既如果關閉了一個方向數據傳輸,那么這個方向將會被關閉直至完全被關閉或刪除,而不能重新被打開。如果第一次調用了shutdown(0),第二次調用了shutdown(1),那么這時的效果就相當於shutdown(2),也就是雙向關閉socket。

close的定義

#include

int close(int fd);

關閉讀寫。成功則返回0,錯誤返回-1,錯誤碼errno:EBADF表示fd不是一個有效描述符;EINTR表示close函數被信號中斷;EIO表示一個IO錯誤。

二者的區別

close-----關閉本進程的socket id,但鏈接還是開着的,用這個socket id的其它進程還能用這個鏈接,能讀或寫這個socket id。

shutdown--破壞了socket 鏈接,讀的時候可能偵探到EOF結束符,寫的時候可能會收到一個SIGPIPE信號,這個信號可能直到socket buffer被填充了才收到,shutdown有一個關閉方式的參數,0 不能再讀,1不能再寫,2 讀寫都不能。

socket 多進程中的 shutdown、close 的使用

當所有的數據操作結束以后,你可以調用close()函數來釋放該socket,從而停止在該socket上的任何數據操作:close(sockfd);使用close中止一個連接,但它只是減少描述符的參考數,並不直接關閉連接,只有當描述符的參考數為0時才關閉連接。所以在多進程/線程程序中,close只是確保了對於某個特定的進程或線程來說,該連接是關閉的。使用 client_fd = accept() 后 fork() 以在子進程中處理請求,此時在父進程中使用 close() 關閉該連接,子進程仍可以繼續使用該連接。

也可以調用shutdown()函數來關閉該socket。該函數允許你只停止在某個方向上的數據傳輸,而一個方向上的數據傳輸繼續進行。如你可以關閉某socket的寫操作而允許繼續在該socket上接受數據,直至讀入所有數據。int shutdown(int sockfd,int how);shutdown可直接關閉描述符,不考慮描述符的參考數,可選擇中止一個方向的連接。

注意

1.如果有多個進程共享一個套接字,close每被調用一次,計數減1,直到計數為0時,也就是所用進程都調用了close,套接字將被釋放。

2.在多進程中如果一個進程中shutdown(sfd, SHUT_RDWR)后其它的進程將無法進行通信。如果一個進程close(sfd)將不會影響到其它進程,得自己理解引用計數的用法了。有Kernel編程知識的更好理解了.

更多關於close和shutdown的說明

1.只要TCP棧的讀緩沖里還有未讀取(read)數據,則調用close時會直接向對端發送RST。

2.shutdown與socket描述符沒有關系,即使調用shutdown(fd, SHUT_RDWR)也不會關閉fd,最終還需close(fd)。

3.可以認為shutdown(fd, SHUT_RD)是空操作,因為shutdown后還可以繼續從該socket讀取數據,這點也許還需要進一步證實。在已發送FIN包后write該socket描述符會引發EPIPE/SIGPIPE。

4.當有多個socket描述符指向同一socket對象時,調用close時首先會遞減該對象的引用計數,計數為0時才會發送FIN包結束TCP連接。shutdown不同,只要以SHUT_WR/SHUT_RDWR方式調用即發送FIN包。

5.SO_LINGER與close,當SO_LINGER選項開啟但超時值為0時,調用close直接發送RST(這樣可以避免進入TIME_WAIT狀態,但破壞了TCP協議的正常工作方式),SO_LINGER對shutdown無影響。

6.TCP連接上出現RST與隨后可能的TIME_WAIT狀態沒有直接關系,主動發FIN包方必然會進入TIME_WAIT狀態,除非不發送FIN而直接以發送RST結束連接。

應用場景

通常來說,socket是雙向的,即數據是雙向通信的。但有些時候,你會想在socket上實現單向的socket,即數據往一個方向傳輸。單向的socket便稱為半開放Socket。要實現半開放式,需要用到shutdown()函數。

一般來說,半開放socket適用於以下場合:

1.當你想要確保所有寫好的數據已經發送成功時。如果在發送數據的過程中,網絡意外斷開或者出現異常,系統不一定會返回異常,這是你可能以為對端已經接收到數據了。這時需要用shutdown()來確定數據是否發送成功,因為調用shutdown()時只有在緩存中的數據全部發送成功后才會返回。

2.想用一種方法來捕獲程序潛在的錯誤,這錯誤可能是因為往一個不能寫的socket上寫數據,也有可能是在一個不該讀操作的socket上讀數據。當程序嘗試這樣做時,將會捕獲到一個異常,捕獲異常對於程序排錯來說是相對簡單和省勁的。

3.當您的程序使用了fork()或者使用多線程時,你想防止其他線程或進程訪問到該資源,又或者你想立刻關閉這個socket,那么可以用shutdown()來實現。

參考

http://blog.csdn.net/pingnanlee/article/details/8426712

http://blog.csdn.net/moxiaomomo/article/details/7897943

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值