您好,登錄后才能下訂單哦!
這篇文章給大家介紹如何進(jìn)一步的tcp使用,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助。
以前對(duì)socket的了解僅僅局限于listen/connect/epoll/select/close等這些API的表面使用。其具體語義以及一些狀態(tài)都沒有深究??傆X得這樣寫代碼會(huì)出問題,今天咬咬牙把《tcp協(xié)議卷1》中的Tcp部分又看了一遍。發(fā)現(xiàn)由于對(duì)協(xié)議和API語義的了解不足,在程序中還是犯了不少錯(cuò)誤。
TIME_WAIT狀態(tài)是tcp網(wǎng)絡(luò)編程中最不容易理解的地方。主動(dòng)關(guān)閉的一方會(huì)經(jīng)歷TIME_WAIT狀態(tài), 這個(gè)狀態(tài)會(huì)經(jīng)歷2MSL的時(shí)間。其目的就是為了可靠的實(shí)現(xiàn)TCP全雙工連接的終止和允許老的重復(fù)分組消逝在網(wǎng)絡(luò)中(具體可以參看UNP P37)。
TIME_WAIT的持續(xù)時(shí)間一般是1分鐘到4分鐘,如果在這段時(shí)間內(nèi)涌入大量連接,然后服務(wù)器將其斷開,就會(huì)導(dǎo)致在服務(wù)器上殘留大量處理TIME_WAIT的連接,理論上這會(huì)嚴(yán)重拖慢系統(tǒng)的性能。
因此,只要條件允許,應(yīng)該盡量讓客戶端來主動(dòng)斷開連接。
由于服務(wù)器綁定的是固定端口,當(dāng)重啟服務(wù)器時(shí),只要還存在有通過這個(gè)固定端口接入進(jìn)來的TIME_WAIT狀態(tài)的連接,就會(huì)導(dǎo)致bind失敗。因此服務(wù)器一定要為bind的socket設(shè)置SO_REUSEADDR屬性。
close的默認(rèn)行為首先對(duì)描述符引用計(jì)數(shù)減一,如果引用計(jì)數(shù)為為0則執(zhí)行close流程。即把該socket標(biāo)記為關(guān)閉, 然后立即返回到調(diào)用進(jìn)程,該socket不能再被調(diào)用進(jìn)程使用。然而tcp將嘗試發(fā)送已經(jīng)排隊(duì)等待發(fā)送到對(duì)端的任何數(shù)據(jù),發(fā)送完閉后才會(huì)執(zhí)行正常的tcp連接終止序列(即四次揮手). 這個(gè)行為可以通過SO_LINGER更改。
相比close, shutdown的行為則更為粗爆一些。
不管有多少進(jìn)程在持有這個(gè)socket,一旦這個(gè)socket被shutdown, 那么所有的進(jìn)程均不能再對(duì)此socket進(jìn)行已經(jīng)shutdown過的操作。shutdown可以分別關(guān)閉讀和寫。
shutdown寫時(shí)會(huì)將當(dāng)前發(fā)送緩沖區(qū)中的數(shù)據(jù)都發(fā)送掉才會(huì)進(jìn)行連接終止序列。
shutdown讀時(shí)會(huì)將當(dāng)前接收緩沖區(qū)中的數(shù)據(jù)都請(qǐng)空。
在silly的實(shí)現(xiàn)中,我對(duì)于close的實(shí)現(xiàn)僅僅是粗爆的將所有發(fā)送緩沖區(qū)清空,然后關(guān)閉socket。
對(duì)比系統(tǒng)的close和shutdown函數(shù)可以發(fā)現(xiàn), 這樣做是不對(duì)的,因?yàn)樵趹?yīng)用層調(diào)用close時(shí),有可能數(shù)據(jù)并沒有發(fā)完, 這樣就會(huì)有可能導(dǎo)致客戶端接收到的信息不完成,而造成其他bug.
關(guān)于如何進(jìn)一步的tcp使用就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。