所謂三次握手(Three-Way Handshake)即建立TCP連接重父,就是指建立一個TCP連接時叶沛,需要客戶端和服務(wù)端總共發(fā)送3個包以確認(rèn)連接的建立瘪弓。(一句話概括)
(本文轉(zhuǎn)自:http://www.cnblogs.com/renyuan/p/3431022.html )
在TCP/IP協(xié)議中劫映,TCP協(xié)議提供可靠的連接服務(wù)乓旗,采用三次握手建立一個連接府蛇。
第一次握手:建立連接時,客戶端發(fā)送syn包(syn=j)到服務(wù)器屿愚,并進(jìn)入SYN_SEND狀態(tài)汇跨,等待服務(wù)器確認(rèn);
第二次握手:服務(wù)器收到syn包妆距,必須確認(rèn)客戶的SYN(ack=j+1)穷遂,同時自己也發(fā)送一個SYN包(syn=k),即SYN+ACK包娱据,此時服務(wù)器進(jìn)入SYN_RECV狀態(tài)蚪黑;
第三次握手:客戶端收到服務(wù)器的SYN+ACK包,向服務(wù)器發(fā)送確認(rèn)包ACK(ack=k+1)中剩,此包發(fā)送完畢忌穿,客戶端和服務(wù)器進(jìn)入ESTABLISHED狀態(tài),完成三次握手结啼。
完成三次握手掠剑,客戶端與服務(wù)器開始傳送數(shù)據(jù),在上述過程中郊愧,還有一些重要的概念:
未連接隊列:在三次握手協(xié)議中朴译,服務(wù)器維護(hù)一個未連接隊列,該隊列為每個客戶端的SYN包(syn=j)開設(shè)一個條目属铁,該條目表明服務(wù)器已收到SYN 包眠寿,并向客戶發(fā)出確認(rèn),正在等待客戶的確認(rèn)包红选。這些條目所標(biāo)識的連接在服務(wù)器處于Syn_RECV狀態(tài)澜公,當(dāng)服務(wù)器收到客戶的確認(rèn)包時姆另,刪除該條目喇肋,服務(wù)器 進(jìn)入ESTABLISHED狀態(tài)坟乾。
Backlog參數(shù):表示未連接隊列的最大容納數(shù)目。
SYN-ACK 重傳次數(shù) 服務(wù)器發(fā)送完SYN-ACK包蝶防,如果未收到客戶確認(rèn)包甚侣,服務(wù)器進(jìn)行首次重傳,等待一段時間仍未收到客戶確認(rèn)包间学,進(jìn)行第二次重傳殷费,如果重傳次數(shù)超 過系統(tǒng)規(guī)定的最大重傳次數(shù),系統(tǒng)將該連接信息從半連接隊列中刪除低葫。注意详羡,每次重傳等待的時間不一定相同。
半連接存活時間:是指半連接隊列的條目存活的最長時間嘿悬,也即服務(wù)從收到SYN包到確認(rèn)這個報文無效的最長時間实柠,該時間值是所有重傳請求包的最長等待時間總和。有時我們也稱半連接存活時間為Timeout時間善涨、SYN_RECV存活時間窒盐。
現(xiàn)在,我們來看一個完整的流程钢拧,在一個TCP socket上系統(tǒng)調(diào)用connect究竟是如何建立起一個到對端的連接的蟹漓。我們還是以實驗環(huán)境172.16.48.2向172.16.48.1的端口5002發(fā)起連接請求為例。
第一步源内,172.16.48.2向172.16.48.1發(fā)起連接請求葡粒,發(fā)送一個SYN段,指明目的端口5002姿锭,通告自己的初始序號(ISN塔鳍,由協(xié)議棧 隨機(jī)產(chǎn)生的一個32位數(shù)),設(shè)置確認(rèn)序號為0(因為還沒有收到過對端的數(shù)據(jù))呻此,通告自己的滑動窗口大小為5840(對端是5792轮纫,這似乎有問題,有待進(jìn) 一步細(xì)查)焚鲜,窗口擴(kuò)大因子為2(在首部選項中)掌唾,通告最大報文段長度為1460(本地局域網(wǎng)),下面是數(shù)據(jù)內(nèi)容(已剝?nèi)ユ溌穼拥囊蕴W(wǎng)首部和網(wǎng)絡(luò)層的IP 首部):
數(shù)據(jù)內(nèi)容 含義
基本首部
80 0e 源端口(32782)
13 8a 目的端口(5002)
00 00 07 bc 初始序號ISN
00 00 00 00 確認(rèn)序號
a 首部長度
0 02 標(biāo)志位忿磅,SYN=1
16 d0 滑動窗口大小(5840)
64 9e 校驗和
00 00 緊急指針
TCP選項
02 04 05 b4 最大報文段長度(1460)
04 02 允許SACK
08 0a 00 0a 79 14 00 00 00 00 時間戳(0x000a7914)糯彬,回顯時間戳(0)
01 占位。
03 03 02 窗口擴(kuò)大因子(2)
第二步葱她,172.16.48.1收到請求包撩扒,檢查標(biāo)志位,發(fā)現(xiàn)SYN=1吨些,認(rèn)為這是一個初始化連接的請求搓谆,回應(yīng)這個SYN炒辉,同時也發(fā)送自己的SYN段(即 ACK,SYN同時置位)。因為SYN本身要占用一個序號(還有標(biāo)志FIN也要占用一個序號)泉手。所以黔寇,確認(rèn)序號設(shè)置為172.16.48.2的ISN加1 (即172.16.48.1期望收到來自172.16.48.2的下一個包的第一個序號為0x07bd。同時也要通告自己的初始序號斩萌,滑動窗口大小缝裤,窗口 擴(kuò)大因子,最大報文段長度等颊郎,下面是數(shù)據(jù)內(nèi)容:
數(shù)據(jù)內(nèi)容 含義
基本TCP首部
13 8a 源端口(5002)
80 0e 目的端口(32782)
98 8e 40 91 初始序號ISN
00 00 07 bd 確認(rèn)序號(對端ISN+1)
a 首部長度
0 12 標(biāo)志位憋飞,ACK=1, SYN=1
16 a0 滑動窗口大小
65 d7 校驗和
00 00 緊急指針
TCP選項
02 04 05 b4 最大報文段長度(1460)
04 02 允許SACK
08 0a 00 3c 25 8a 00 0a 79 14 時間戳(0x003c258a),回顯時間戳(000a7914)
01 占位
03 03 02 窗口擴(kuò)大因子(2)
第三步姆吭,172.16.48.2對來自172.16.48.1的SYN段進(jìn)行確認(rèn)搀崭,至此,TCP三次握手協(xié)議完成猾编,連接建立瘤睹,在172.16.48.2收 到SYN段時,將自己對應(yīng)的socket的狀態(tài)由TCP_SYN_SENT改為TCP_ESTABLISHED答倡,進(jìn)入連接建立狀態(tài)轰传,下面是數(shù)據(jù)內(nèi)容:
數(shù)據(jù)內(nèi)容 含義
80 0e 源端口(32782)
13 8a 目的端口(5002)
00 00 07 bd 序號(已不是ISN了)
98 8e 40 92 確認(rèn)序號(對端ISN+1)
8 首部長度(8*4=32,有12字節(jié)的選項)
0 10 標(biāo)志,ACK=1
05 b4 滑動窗口大小(1460瘪撇,有問題获茬?待確認(rèn))
a5 8a 校驗和
00 00 緊急指針
01 占位
01 占位
08 0a 00 0a 79 14 00 3c 25 8a 時間戳(0x0a007914), 回顯時間戳(0x003c258a)
=====================================================================
7、簡述TCP三次握手過程倔既,并說明為什么要3次握手
TCP 三次握手
TCP 連接是通過三次握手進(jìn)行初始化的恕曲。三次握手的目的是同步連接雙方的序列號和確認(rèn)號并交換 TCP 窗口大小信息。以下步驟概述了通常情況下客戶端計算機(jī)聯(lián)系服務(wù)器計算機(jī)的過程:
1. 客戶端向服務(wù)器發(fā)送一個SYN置位的TCP報文渤涌,其中包含連接的初始序列號x和一個窗口大信逡ァ(表示客戶端上用來存儲從服務(wù)器發(fā)送來的傳入段的緩沖區(qū)的大小)实蓬。
2. 服務(wù)器收到客戶端發(fā)送過來的SYN報文后茸俭,向客戶端發(fā)送一個SYN和ACK都置位的TCP報文,其中包含它選擇的初始序列號y安皱、對客戶端的序列號的確認(rèn)x+1和一個窗口大械鼢蕖(表示服務(wù)器上用來存儲從客戶端發(fā)送來的傳入段的緩沖區(qū)的大小)酌伊。
3. .客戶端接收到服務(wù)器端返回的SYN+ACK報文后腾窝,向服務(wù)器端返回一個確認(rèn)號y+1和序號x+1的ACK報文,一個標(biāo)準(zhǔn)的TCP連接完成。
TCP 使用類似的握手過程來結(jié)束連接虹脯。這可確保兩個主機(jī)均能完成傳輸并確保所有的數(shù)據(jù)均得以接收
TCP Client Flags TCP Server
1 Send SYN (seq=x) ----SYN---> SYN Received
2 SYN/ACK Received <---SYN/ACK---- Send SYN (seq=y)辜贵, ACK (x+1)
3 Send ACK (y+1) ----ACK---> ACK Received, Connection Established
w: ISN (Initial Sequence Number) of the Client
x: ISN of the Server
==========================================================
握手階段:
序號 方向 seq ack
1 A->B 10000 0
2 B->A 20000 10000+1=10001
3 A->B 10001 20000+1=20001
解釋:
1:A向B發(fā)起連接請求归形,以一個隨機(jī)數(shù)初始化A的seq,這里假設(shè)為10000,此時ACK=0
2:B收到A的連接請求后鼻由,也以一個隨機(jī)數(shù)初始化B的seq暇榴,這里假設(shè)為20000,意思是:你的請求我已收到蕉世,我這方的數(shù)據(jù)流就從這個數(shù)開始蔼紧。B的ACK是A的seq加1,即10000+1=10001
3:A收到B的回復(fù)后狠轻,它的seq是它的上個請求的seq加1奸例,即10000+1=10001,意思也是:你的回復(fù)我收到了向楼,我這方的數(shù)據(jù)流就從這個數(shù)開始查吊。A此時的ACK是B的seq加1,即20000+1=20001
數(shù)據(jù)傳輸階段:
序號 方向 seq ack size
23 A->B 40000 70000 1514
24 B->A 70000 40000+1514-54=41460 54
25 A->B 41460 70000+54-54=70000 1514
26 B->A 70000 41460+1514-54=42920 54
解釋:
23:B接收到A發(fā)來的seq=40000,ack=30000,size=1514的數(shù)據(jù)包
24:于是B向A也發(fā)一個數(shù)據(jù)包湖蜕,告訴B逻卖,你的上個包我收到了。B的seq就以它收到的數(shù)據(jù)包的ACK填充昭抒,ACK是它收到的數(shù)據(jù)包的SEQ加上數(shù)據(jù)包的大小(不包括以太網(wǎng)協(xié)議頭评也,IP頭,TCP頭)灭返,以證實B發(fā)過來的數(shù)據(jù)全收到了盗迟。
25:A在收到B發(fā)過來的seq為41460的數(shù)據(jù)包時,一看到41460熙含,正好是它的上個數(shù)據(jù)包的seq加上包的大小罚缕,就明白,上次發(fā)送的數(shù)據(jù)包已安全 到達(dá)怎静。于是它再發(fā)一個數(shù)據(jù)包給B怕磨。這個正在發(fā)送的數(shù)據(jù)包的seq也以它收到的數(shù)據(jù)包的ACK填充,ACK就以它收到的數(shù)據(jù)包的seq(70000)加上包 的size(54)填充,即ack=70000+54-54(全是頭長消约,沒數(shù)據(jù)項)肠鲫。
26:一樣的啊


在TCP/IP協(xié)議中,TCP協(xié)議提供可靠的連接服務(wù)或粮,采用三次握手建立一個連接导饲,如圖1所示。
(1) 第一次握手:建立連接時,客戶端A發(fā)送SYN包(SYN=j)到服務(wù)器B渣锦,并進(jìn)入SYN_SEND狀態(tài)硝岗,等待服務(wù)器B確認(rèn)。
(2) 第二次握手:服務(wù)器B收到SYN包袋毙,必須確認(rèn)客戶A的SYN(ACK=j+1)型檀,同時自己也發(fā)送一個SYN包(SYN=k),即SYN+ACK包听盖,此時服務(wù)器B進(jìn)入SYN_RECV狀態(tài)胀溺。
(3) 第三次握手:客戶端A收到服務(wù)器B的SYN+ACK包,向服務(wù)器B發(fā)送確認(rèn)包ACK(ACK=k+1)皆看,此包發(fā)送完畢仓坞,客戶端A和服務(wù)器B進(jìn)入ESTABLISHED狀態(tài),完成三次握手腰吟。
完成三次握手无埃,客戶端與服務(wù)器開始傳送數(shù)據(jù)。
圖1 TCP三次握手建立連接
由于TCP連接是全雙工的毛雇,因此每個方向都必須單獨(dú)進(jìn)行關(guān)閉嫉称。這個原則是當(dāng)一方完成它的數(shù)據(jù)發(fā)送任務(wù)后就能發(fā)送一個FIN來終止這個方向的連接。收到一個 FIN只意味著這一方向上沒有數(shù)據(jù)流動灵疮,一個TCP連接在收到一個FIN后仍能發(fā)送數(shù)據(jù)澎埠。首先進(jìn)行關(guān)閉的一方將執(zhí)行主動關(guān)閉,而另一方執(zhí)行被動關(guān)閉始藕。
(1)客戶端A發(fā)送一個FIN蒲稳,用來關(guān)閉客戶A到服務(wù)器B的數(shù)據(jù)傳送(報文段4)。
(2)服務(wù)器B收到這個FIN伍派,它發(fā)回一個ACK江耀,確認(rèn)序號為收到的序號加1(報文段5)。和SYN一樣诉植,一個FIN將占用一個序號祥国。
(3)服務(wù)器B關(guān)閉與客戶端A的連接,發(fā)送一個FIN給客戶端A(報文段6)晾腔。
(4)客戶端A發(fā)回ACK報文確認(rèn)舌稀,并將確認(rèn)序號設(shè)置為收到序號加1(報文段7)。
TCP采用四次揮手關(guān)閉連接如圖2所示灼擂。
圖2 TCP四次揮手關(guān)閉連接
1.為什么建立連接協(xié)議是三次握手壁查,而關(guān)閉連接卻是四次握手呢?
這是因為服務(wù)端的LISTEN狀態(tài)下的SOCKET當(dāng)收到SYN報文的連接請求后剔应,它可以把ACK和SYN(ACK起應(yīng)答作用睡腿,而SYN起同步作用)放在一個報文里來發(fā)送语御。但關(guān)閉連接時,當(dāng)收到對方的FIN報文通知時席怪,它僅僅表示對方?jīng)]有數(shù)據(jù)發(fā)送給你了应闯;但未必你所有的數(shù)據(jù)都全部發(fā)送給對方了,所以你可能未必會馬上會關(guān)閉SOCKET,也即你可能還需要發(fā)送一些數(shù)據(jù)給對方之后挂捻,再發(fā)送FIN報文給對方來表示你同意現(xiàn)在可以關(guān)閉連接了碉纺,所以它這里的ACK報文和FIN報文多數(shù)情況下都是分開發(fā)送的。
2.為什么TIME_WAIT狀態(tài)還需要等2MSL后才能返回到CLOSED狀態(tài)刻撒?
TIME_WAIT狀態(tài)由兩個存在的理由骨田。
****(1)可靠的實現(xiàn)TCP全雙工鏈接的終止****
這是因為雖然雙方都同意關(guān)閉連接了,而且握手的4個報文也都協(xié)調(diào)和發(fā)送完畢疫赎,按理可以直接回到CLOSED狀態(tài)(就好比從SYN_SEND狀態(tài)到ESTABLISH狀態(tài)那樣);但是因為我們必須要假想網(wǎng)絡(luò)是不可靠的碎节,你無法保證你最后發(fā)送的ACK報文會一定被對方收到捧搞,因此對方處于LAST_ACK狀態(tài)下的SOCKET可能會因為超時未收到ACK報文,而重發(fā)FIN報文狮荔,所以這個TIME_WAIT狀態(tài)的作用就是用來重發(fā)可能丟失的ACK報文胎撇。
** (2)允許老的重復(fù)的分節(jié)在網(wǎng)絡(luò)中消逝**
假設(shè)在12.106.32.254的1500端口和206.168.1.112.219的21端口之間有一個TCP連接。我們關(guān)閉這個鏈接殖氏,過一段時間后在相同的IP地址和端口建立另一個連接晚树。后一個鏈接成為前一個的化身。因為它們的IP地址和端口號都相同雅采。TCP必須防止來自某一個連接的老的重復(fù)分組在連接已經(jīng)終止后再現(xiàn)爵憎,從而被誤解成屬于同一鏈接的某一個某一個新的化身。為做到這一點(diǎn)婚瓜,TCP將不給處于TIME_WAIT狀態(tài)的鏈接發(fā)起新的化身宝鼓。既然TIME_WAIT狀態(tài)的持續(xù)時間是MSL的2倍,這就足以讓某個方向上的分組最多存活msl秒即被丟棄巴刻,另一個方向上的應(yīng)答最多存活msl秒也被丟棄愚铡。通過實施這個規(guī)則,我們就能保證每成功建立一個TCP連接時胡陪。來自該鏈接先前化身的重復(fù)分組都已經(jīng)在網(wǎng)絡(luò)中消逝了沥寥。
3. 為什么不能用兩次握手進(jìn)行連接?
我們知道柠座,3次握手完成兩個重要的功能邑雅,既要雙方做好發(fā)送數(shù)據(jù)的準(zhǔn)備工作(雙方都知道彼此已準(zhǔn)備好),也要允許雙方就初始序列號進(jìn)行協(xié)商妈经,這個序列號在握手過程中被發(fā)送和確認(rèn)蒂阱。
現(xiàn)在把三次握手改成僅需要兩次握手锻全,死鎖是可能發(fā)生的。作為例子录煤,考慮計算機(jī)S和C之間的通信鳄厌,假定C給S發(fā)送一個連接請求分組,S收到了這個分組妈踊,并發(fā) 送了確認(rèn)應(yīng)答分組了嚎。按照兩次握手的協(xié)定,S認(rèn)為連接已經(jīng)成功地建立了廊营,可以開始發(fā)送數(shù)據(jù)分組歪泳。可是露筒,C在S的應(yīng)答分組在傳輸中被丟失的情況下呐伞,將不知道S 是否已準(zhǔn)備好,不知道S建立什么樣的序列號慎式,C甚至懷疑S是否收到自己的連接請求分組伶氢。在這種情況下,C認(rèn)為連接還未建立成功瘪吏,將忽略S發(fā)來的任何數(shù)據(jù)分 組癣防,只等待連接確認(rèn)應(yīng)答分組。而S在發(fā)出的分組超時后掌眠,重復(fù)發(fā)送同樣的分組蕾盯。這樣就形成了死鎖。
補(bǔ)充:
a. 默認(rèn)情況下(不改變socket選項)蓝丙,當(dāng)你調(diào)用close( or closesocket级遭,以下說close不再重復(fù))時,如果發(fā)送緩沖中還有數(shù)據(jù)渺尘,TCP會繼續(xù)把數(shù)據(jù)發(fā)送完装畅。
b. 發(fā)送了FIN只是表示這端不能繼續(xù)發(fā)送數(shù)據(jù)(應(yīng)用層不能再調(diào)用send發(fā)送),但是還可以接收數(shù)據(jù)沧烈。
c. 應(yīng)用層如何知道對端關(guān)閉掠兄?通常,在最簡單的阻塞模型中锌雀,當(dāng)你調(diào)用recv時蚂夕,如果返回0,則表示對端關(guān)閉腋逆。在這個時候通常的做法就是也調(diào)用close婿牍,那么TCP層就發(fā)送FIN,繼續(xù)完成四次握手惩歉。如果你不調(diào)用close等脂,那么對端就會處于FIN_WAIT_2狀態(tài)俏蛮,而本端則會處于CLOSE_WAIT狀態(tài)。這個可以寫代碼試試上遥。
d. 在很多時候搏屑,TCP連接的斷開都會由TCP層自動進(jìn)行,例如你CTRL+C終止你的程序粉楚,TCP連接依然會正常關(guān)閉辣恋,你可以寫代碼試試。
插曲:
特別的TIME_WAIT狀態(tài):
從以上TCP連接關(guān)閉的狀態(tài)轉(zhuǎn)換圖可以看出模软,主動關(guān)閉的一方在**發(fā)送完**對對方FIN報文的確認(rèn)(ACK)報文后伟骨,會進(jìn)入**TIME_WAIT狀態(tài)**。TIME_WAIT狀態(tài)**也稱為2MSL狀態(tài)**燃异。什么是2MSL携狭?MSL即Maximum Segment Lifetime,也就是報文最大生存時間回俐,引用《TCP/IP詳解》中的話:“它(MSL)是任何報文段被丟棄前在網(wǎng)絡(luò)內(nèi)的最長時間逛腿。”那么鲫剿,2MSL也就是這個時間的2倍鳄逾。其實我覺得沒必要把這個MSL的確切含義搞明白稻轨,你所需要明白的是灵莲,當(dāng)TCP連接完成四個報文段的交換時,主動關(guān)閉的一方將繼續(xù)等待一定時間(2-4分鐘)殴俱,即使兩端的應(yīng)用程序結(jié)束政冻。你可以寫代碼試試,然后用netstat查看下线欲。
為什么需要2MSL明场?根據(jù)《TCP/IP詳解》和《The TCP/IP Guide》中的說法,有兩個原因:
其一李丰,保證發(fā)送的ACK會成功發(fā)送到對方苦锨,如何保證?我覺得可能是通過超時計時器發(fā)送趴泌。這個就很難用代碼演示了舟舒。
其二,報文可能會被混淆嗜憔,意思是說秃励,其他時候的連接可能會被當(dāng)作本次的連接。直接引用《The TCP/IP Guide》的說法:The second is to provide a “buffering period”between the end of this connection and any subsequent ones. If not for this period, it is possible that packets from different connections could be mixed, creating confusion.
TIME_WAIT狀態(tài)所帶來的影響:
當(dāng)某個連接的一端處于TIME_WAIT狀態(tài)時吉捶,該連接將不能再被使用夺鲜。事實上皆尔,對于我們比較有現(xiàn)實意義的是,這個端口將不能再被使用币励。某個端口處于TIME_WAIT狀態(tài)(其實應(yīng)該是這個連接)時慷蠕,這意味著這個TCP連接并沒有斷開(完全斷開),那么榄审,如果你bind這個端口砌们,就會失敗。對于服務(wù)器而言搁进,如果服務(wù)器突然crash掉了浪感,那么它將無法再2MSL內(nèi)重新啟動,因為bind會失敗饼问。解決這個問題的一個方法就是設(shè)置socket的SO_REUSEADDR選項影兽。這個選項意味著你可以重用一個地址。
對于TIME_WAIT的插曲:
當(dāng)建立一個TCP連接時莱革,服務(wù)器端會繼續(xù)用原有端口監(jiān)聽峻堰,同時用這個端口與客戶端通信。而客戶端默認(rèn)情況下會使用一個隨機(jī)端口與服務(wù)器端的監(jiān)聽端口通信盅视。有時候捐名,為了服務(wù)器端的安全性,我們需要對客戶端進(jìn)行驗證闹击,即限定某個IP某個特定端口的客戶端镶蹋。客戶端可以使用bind來使用特定的端口赏半。對于服務(wù)器端贺归,當(dāng)設(shè)置了SO_REUSEADDR選項時,它可以在2MSL內(nèi)啟動并listen成功断箫。但是對于客戶端拂酣,當(dāng)使
用bind并設(shè)置SO_REUSEADDR時,如果在2MSL內(nèi)啟動仲义,雖然bind會成功婶熬,但是在windows平臺上connect會失敗。而在linux上則不存在這個問題埃撵。(我的實驗平臺:winxp, ubuntu7.10)
要解決windows平臺的這個問題赵颅,可以設(shè)置SO_LINGER選項。SO_LINGER選項決定調(diào)用close時TCP的行為盯另。SO_LINGER涉及到linger結(jié)構(gòu)體性含,如果設(shè)置結(jié)構(gòu)體中l(wèi)_onoff為非0,l_linger為0鸳惯,那么調(diào)用close時TCP連接會立刻斷開商蕴,TCP不會將發(fā)送緩沖中未發(fā)送的數(shù)據(jù)發(fā)送叠萍,而是立即發(fā)送一個RST報文給對方,這個時候TCP連接就不會進(jìn)入TIME_WAIT狀態(tài)绪商。如你所見苛谷,這樣做雖然解決了問題,但是并不安全格郁。通過以上方式設(shè)置SO_LINGER狀態(tài)腹殿,等同于設(shè)置SO_DONTLINGER狀態(tài)。
斷開連接時的意外:
這個算不上斷開連接時的意外例书,當(dāng)TCP連接發(fā)生一些物理上的意外情況時锣尉,例如網(wǎng)線斷開,linux上的TCP實現(xiàn)會依然認(rèn)為該連接有效决采,而windows則會在一定時間后返回錯誤信息自沧。這似乎可以通過設(shè)置SO_KEEPALIVE選項來解決,不過不知道這個選項是否對于所有平臺都有效树瞭。
(轉(zhuǎn)自:http://www.cnblogs.com/renyuan/p/3431022.html )