日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

close和shutdown的区别

發(fā)布時(shí)間:2025/4/16 编程问答 52 豆豆
生活随笔 收集整理的這篇文章主要介紹了 close和shutdown的区别 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

轉(zhuǎn)的,沒驗(yàn)證

close(sock_fd)會(huì)把sock_fd的內(nèi)部計(jì)數(shù)器減1
當(dāng)sock_fd的內(nèi)部計(jì)數(shù)器為0時(shí), 才調(diào)用shutodwn(), 并最終釋放文件描述符
調(diào)用shutdown()只是進(jìn)行了TCP斷開, 并沒有釋放文件描述符

本來正常的TCP程序不需要顯示調(diào)用shutdown()
但某些TCP程序十分不友好, 包括著名的firefox早期版本, 給服務(wù)器吃CLOSE_WAIT
調(diào)用shutodwn()就不會(huì)CLOSE_WAIT, 只會(huì)FIN_WAIT1或FIN_WAIT2

?

這就是服務(wù)器沒有調(diào)用shutdown引起的
客戶端非正常退出會(huì)給服務(wù)器帶來CLOSE_WAIT

CLOSE_WAIT非常討厭, 會(huì)卡住(阻塞)close()函數(shù)

?

?

以下描述主要是針對(duì)windows平臺(tái)下的TCP socket而言。

首先需要區(qū)分一下關(guān)閉socket和關(guān)閉TCP連接的區(qū)別,關(guān)閉TCP連接是指TCP協(xié)議層的東西,就是兩個(gè)TCP端之間交換了一些協(xié)議包(FIN,RST等),具體的交換過程可以看TCP協(xié)議,這里不詳細(xì)描述了。而關(guān)閉socket是指關(guān)閉用戶應(yīng)用程序中的socket句柄,釋放相關(guān)資源。但是當(dāng)用戶關(guān)閉socket句柄時(shí)會(huì)隱含的觸發(fā)TCP連接的關(guān)閉過程。

TCP連接的關(guān)閉過程有兩種,一種是優(yōu)雅關(guān)閉(graceful close),一種是強(qiáng)制關(guān)閉(hard close或abortive close)。所謂優(yōu)雅關(guān)閉是指,如果發(fā)送緩存中還有數(shù)據(jù)未發(fā)出則其發(fā)出去,并且收到所有數(shù)據(jù)的ACK之后,發(fā)送FIN包,開始關(guān)閉過程。而強(qiáng)制關(guān)閉是指如果緩存中還有數(shù)據(jù),則這些數(shù)據(jù)都將被丟棄,然后發(fā)送RST包,直接重置TCP連接。

?

下面說一下shutdown及closesocket函數(shù)。

shutdown函數(shù)的原型是:

int shutdown(

??SOCKET s,

??int how

);

該函數(shù)用于關(guān)閉TCP連接,單并不關(guān)閉socket句柄。其第二個(gè)參數(shù)可以取三個(gè)值:SD_RECEIVE,SD_SEND,SD_BOTH。

SD_RECEIVE表明關(guān)閉接收通道,在該socket上不能再接收數(shù)據(jù),如果當(dāng)前接收緩存中仍有未取出數(shù)據(jù)或者以后再有數(shù)據(jù)到達(dá),則TCP會(huì)向發(fā)送端發(fā)送RST包,將連接重置。

SD_SEND表明關(guān)閉發(fā)送通道,TCP會(huì)將發(fā)送緩存中的數(shù)據(jù)都發(fā)送完畢并收到所有數(shù)據(jù)的ACK后向?qū)Χ税l(fā)送FIN包,表明本端沒有更多數(shù)據(jù)發(fā)送。這個(gè)是一個(gè)優(yōu)雅關(guān)閉過程。

SD_BOTH則表示同時(shí)關(guān)閉接收通道和發(fā)送通道。

?

From:?http://blog.csdn.net/bad_sheep/article/details/6157738

?

?

closesocket函數(shù)的原型是:

int closesocket(

??SOCKET s

);

該函數(shù)用于關(guān)閉socket句柄,并釋放相關(guān)資源。前面說過,關(guān)閉socket句柄時(shí)會(huì)隱含觸發(fā)TCP連接的關(guān)閉過程,那么closesocket觸發(fā)的是一個(gè)優(yōu)雅關(guān)閉過程還是強(qiáng)制關(guān)閉過程呢?這個(gè)與一個(gè)socket選項(xiàng)有關(guān):SO_LINGER 選項(xiàng),該選項(xiàng)的設(shè)置值決定了closesocket的行為。該選項(xiàng)的參數(shù)值是linger結(jié)構(gòu),其定義是:

typedef struct linger {

??u_short l_onoff;

??u_short l_linger;

} linger;

當(dāng)l_onoff值設(shè)置為0時(shí),closesocket會(huì)立即返回,并關(guān)閉用戶socket句柄。如果此時(shí)緩沖區(qū)中有未發(fā)送數(shù)據(jù),則系統(tǒng)會(huì)在后臺(tái)將這些數(shù)據(jù)發(fā)送完畢后關(guān)閉TCP連接,是一個(gè)優(yōu)雅關(guān)閉過程,但是這里有一個(gè)副作用就是socket的底層資源會(huì)被保留直到TCP連接關(guān)閉,這個(gè)時(shí)間用戶應(yīng)用程序是無法控制的。

當(dāng)l_onoff值設(shè)置為非0值,而l_linger也設(shè)置為0,那么closesocket也會(huì)立即返回并關(guān)閉用戶socket句柄,但是如果此時(shí)緩沖區(qū)中有未發(fā)送數(shù)據(jù),TCP會(huì)發(fā)送RST包重置連接,所有未發(fā)數(shù)據(jù)都將丟失,這是一個(gè)強(qiáng)制關(guān)閉過程。

當(dāng)l_onoff值設(shè)置為非0值,而l_linger也設(shè)置為非0值時(shí),同時(shí)如果socket是阻塞式的,此時(shí)如果緩沖區(qū)中有未發(fā)送數(shù)據(jù),如果TCP在l_linger表明的時(shí)間內(nèi)將所有數(shù)據(jù)發(fā)出,則發(fā)完后關(guān)閉TCP連接,這時(shí)是優(yōu)雅關(guān)閉過程;如果如果TCP在l_linger表明的時(shí)間內(nèi)沒有將所有數(shù)據(jù)發(fā)出,則會(huì)丟棄所有未發(fā)數(shù)據(jù)然后TCP發(fā)送RST包重置連接,此時(shí)就是一個(gè)強(qiáng)制關(guān)閉過程了。

另外還有一個(gè)socket選項(xiàng)SO_DONTLINGER,它的參數(shù)值是一個(gè)bool類型的,如果設(shè)置為true,則等價(jià)于SO_LINGER中將l_onoff設(shè)置為0。

注意SO_LINGER和SO_DONTLINGER選項(xiàng)只影響closesocket的行為,而與shutdown函數(shù)無關(guān),shutdown總是會(huì)立即返回的。

?

所以為了保證建議的最好的關(guān)閉方式是這樣的:

發(fā)送完了所有數(shù)據(jù)后:

(1)調(diào)用shutdown(s, SD_SEND),如果本端同時(shí)也接收數(shù)據(jù)時(shí)則執(zhí)行第二步,否則跳到第4步。

(2)繼續(xù)接收數(shù)據(jù),

(3)收到FD_CLOSE事件后,調(diào)用recv函數(shù)直到recv返回0或-1(保證收到所有數(shù)據(jù)),

(4)調(diào)用closesocket,關(guān)閉socket句柄。

?

在實(shí)際編程中,我們經(jīng)常也不調(diào)用shutdown,而是直接調(diào)用closesocket,利用closesocket隱含觸發(fā)TCP連接關(guān)閉過程的特性。此時(shí)的過程就是:

當(dāng)發(fā)送完所有數(shù)據(jù)后:

(1)如果本端同時(shí)也接受數(shù)據(jù)則則執(zhí)行第二步,否則跳到第4步。

(2)繼續(xù)接收數(shù)據(jù),

(3)收到FD_CLOSE事件后,調(diào)用recv函數(shù)直到recv返回0或-1(保證收到所有數(shù)據(jù)),

(4)調(diào)用closesocket,關(guān)閉socket句柄。

但是此時(shí)為了保證數(shù)據(jù)不丟失,則需要設(shè)置SO_DONTLINGER選項(xiàng),不過windows平臺(tái)下這個(gè)也是默認(rèn)設(shè)置。

?

經(jīng)過實(shí)驗(yàn)發(fā)現(xiàn),發(fā)送端應(yīng)用程序即便是異常退出或被kill掉進(jìn)程,操作系統(tǒng)也不會(huì)丟棄發(fā)送緩沖區(qū)中的未發(fā)送數(shù)據(jù),而是會(huì)在后臺(tái)將這些數(shù)據(jù)發(fā)送出去。但是這是在socket的發(fā)送緩存不為0的前提下,當(dāng)socket的發(fā)送緩存設(shè)置為0(通過SO_SNDBUF選項(xiàng))時(shí)比較特殊,此時(shí)不論socket是否是阻塞的,send函數(shù)都會(huì)被阻塞直到傳入的用戶緩存中的數(shù)據(jù)都被發(fā)送出去并被確認(rèn),因?yàn)榇藭r(shí)在驅(qū)動(dòng)層沒有分配緩存存放用戶數(shù)據(jù),而是直接使用的應(yīng)用層的用戶緩存,所以必須阻塞直到數(shù)據(jù)都發(fā)出,否則可能會(huì)造成系統(tǒng)崩潰。

?

另外,如果是接收端的應(yīng)用程序異常退出或被kill掉進(jìn)程,并且接收緩存中還有數(shù)據(jù)沒有取出的話,那么接收端的TCP會(huì)向發(fā)送端發(fā)送RST包,重置連接,因?yàn)楹罄m(xù)數(shù)據(jù)已經(jīng)無法被提交應(yīng)用層了。

?

最后這里說一個(gè)感覺是windows的bug,就是做這樣的一個(gè)測(cè)試:

在一端線listen一個(gè)socket,然后在另一端connect,connect成功后,listen端會(huì)檢測(cè)到網(wǎng)絡(luò)事件觸發(fā),在listen端accept之前,將connect端kill掉,然后繼續(xù)運(yùn)行l(wèi)isten端,listen端任然會(huì)accept成功,且在accept出來的socket發(fā)送數(shù)據(jù)也能成功。發(fā)送完之后在等網(wǎng)絡(luò)事件,此時(shí)又會(huì)等待成功,但是調(diào)用WSAEnumNetworkEvents得出的事件標(biāo)識(shí)卻是0。之后再也不會(huì)等到網(wǎng)絡(luò)事件。

轉(zhuǎn)載于:https://www.cnblogs.com/liyulong1982/p/3990740.html

總結(jié)

以上是生活随笔為你收集整理的close和shutdown的区别的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。