內(nèi)容根據(jù)哈工大-李全龍、聶蘭順老師-計(jì)算機(jī)網(wǎng)絡(luò)課程總結(jié)整理
建立連接,照我的理解就是通信雙方互相確認(rèn)了對方的存在,并且確定對方也知道自己的存在。也就是你對我的呼叫我收到了,我也知道我給你的回復(fù)你收到了。tcp里的連接,除了這些,通信雙方還要為連接分配資源。比如主機(jī)A的內(nèi)存中維護(hù)了一個變量connectionList,其中的每個connection,指明了雙方的IP和端口號,并且分配了一塊緩沖空間,用來存放收到的數(shù)據(jù)。
建立連接
tcp建立連接,采用三次握手的方式。(three way handshake,三次握手的協(xié)議其實(shí)還有其他,不止tcp)

三次握手是指三次信息交換
第一步:客戶端請求建立連接。發(fā)送syn=1,seq=x
第二步:服務(wù)器同意建立連接,并為連接分配緩存?;貜?fù)ack=x+1,syn=1,seq=y
第三步:客戶端回復(fù)syn=0,ack=y+1,此時可以攜帶正式數(shù)據(jù)
第二步完成后,服務(wù)器的資源會保留一段時間,如果超過一定時間沒有收到ack,就會回收資源。
SYN洪泛攻擊
上面三步的第二步完成后,服務(wù)器為連接分配了資源并會保留一段時間,客戶端不再回復(fù)ack,就造成了服務(wù)器資源的浪費(fèi)。如果同時用大量主機(jī)向同一臺服務(wù)器發(fā)起連接請求,但是不給回復(fù),就會造成服務(wù)器無法正常服務(wù)。這稱為SYN洪泛攻擊。
為什么需要三次握手?
如果一次握手,客戶端發(fā)送建立連接的請求,直接就開始發(fā)送數(shù)據(jù)了,根本不管服務(wù)器是否做好了準(zhǔn)備,甚至連接方(ip+端口)是否存在,顯然不合理。
如果兩次握手
第一次:客戶端請求建立連接
第二次:服務(wù)器就分配資源并回復(fù)ack,連接建立
弊端1:
已失效的連接請求報文段”的產(chǎn)生在這樣一種情況下:client發(fā)出的第一個連接請求報文段并沒有丟失,而是在某個網(wǎng)絡(luò)結(jié)點(diǎn)長時間的滯留了,以致延誤到連接釋放以后的某個時間才到達(dá)server。本來這是一個早已失效的報文段。但server收到此失效的連接請求報文段后,就誤認(rèn)為是client再次發(fā)出的一個新的連接請求。于是就向client發(fā)出確認(rèn)報文段,同意建立連接。假設(shè)不采用“三次握手”,那么只要server發(fā)出確認(rèn),新的連接就建立了。由于現(xiàn)在client并沒有發(fā)出建立連接的請求,因此不會理睬server的確認(rèn),也不會向server發(fā)送數(shù)據(jù)。但server卻以為新的運(yùn)輸連接已經(jīng)建立,并一直等待client發(fā)來數(shù)據(jù)。這樣,server的很多資源就白白浪費(fèi)掉了。采用“三次握手”的辦法可以防止上述現(xiàn)象發(fā)生。例如剛才那種情況,client不會向server的確認(rèn)發(fā)出確認(rèn)。server由于收不到確認(rèn),就知道client并沒有要求建立連接。
---《計(jì)算機(jī)網(wǎng)絡(luò)》謝希仁版
弊端2:
從弊端1的例子知道,服務(wù)器收到連接請求后,不能知道這是一個新的連接請求,還是一個過期的歷史請求,于是按正常思維,它只能認(rèn)為這是一個新的,不然碰上1的錯誤,那不得“端口泄露”。
假如客戶端發(fā)起連接請求(seq=90),超時,然后發(fā)起第二個(seq=100)。
服務(wù)器經(jīng)過漫長的等待,最先收到了第一個(seq=90),于是回復(fù)ack=91。
此時的客戶端希望的是ack=101,知道這是一個過期的歷史連接,但對不上號也就不會發(fā)數(shù)據(jù)。
(因?yàn)榭蛻舳酥肋@是一個歷史連接,假如就用這個歷史連接和服務(wù)器通信的話,如果之后seq=100的那個請求又被服務(wù)器收到了怎么辦)
弊端3:無法同步序列號
服務(wù)器不清楚自己回復(fù)的ack消息是否被收到,也就不確定客戶端是否知道自己選的序列號對方是否知道。
如果該成三次握手,客戶端收到ack,發(fā)現(xiàn)和自己希望的對不上號,于是知道這是一個過期的歷史連接,于是發(fā)送RST報文段,服務(wù)器收到后釋放連接。也能同步序列號。
關(guān)閉連接

客戶端和服務(wù)器都能發(fā)起關(guān)閉請求,這里假設(shè)是由客戶端發(fā)起
第一步:客戶端請求關(guān)閉連接,發(fā)送FIN報文段,進(jìn)入FIN-WAIT-1狀態(tài)。此時客戶端不會再向服務(wù)器發(fā)送數(shù)據(jù),但還可以接收數(shù)據(jù)。
第二步:服務(wù)器回復(fù)ack,進(jìn)入CLOSE-WAIT狀態(tài)??蛻舳耸盏胶筮M(jìn)入FIN-WAIT-2狀態(tài)。
第三步:服務(wù)器回復(fù)FIN,進(jìn)入LAST-ACK狀態(tài)。
第四次:客戶端收到FIN,回復(fù)ack,進(jìn)入TIME-WAIT狀態(tài)。等待2MSL的時間后,客戶端關(guān)閉連接,進(jìn)入CLOSED狀態(tài)。服務(wù)器收到ack,也關(guān)閉連接,進(jìn)入CLOSED狀態(tài)。


當(dāng)服務(wù)收到FIN時,如果沒有要發(fā)送的數(shù)據(jù),也可以直接回復(fù)ACK+FIN,把第二三次握手合并,這樣就成了三次揮手。當(dāng)成三次揮手來理解更容易:
客戶端想關(guān)閉連接,負(fù)責(zé)任的做法是要告知服務(wù)器并確保對方知道,所以第一次消息就出去了。客戶端對服務(wù)器,我想關(guān)閉連接
服務(wù)器收到后同意關(guān)閉,知道對方還在等自己的回復(fù),所以就有了第二次消息。服務(wù)器對客戶端,我同意關(guān)閉,服務(wù)器也要確保自己的回復(fù)對方收到了。
客戶端收到服務(wù)器同意后,立即告知對方自己收到消息了,所以就有了第三次。客戶端對服務(wù)器,我收到了,客戶端然后進(jìn)入等待,一段時間內(nèi)如果沒收到服務(wù)器的消息,就認(rèn)為服務(wù)器收到消息了,然后關(guān)閉連接。