建立一個(gè)TCP連接時(shí)會(huì)發(fā)生下述情形。
(1)服務(wù)器必須準(zhǔn)備好接受外來的連接稳强。這通常通過調(diào)用socket奖地、bind和listen這三個(gè)函數(shù)來完成,我們稱之為被動(dòng)打開(passive open)法竞。
(2)客戶通過調(diào)用connect發(fā)生主動(dòng)打開(active open )耙厚。這導(dǎo)致客戶TCP發(fā)送一個(gè)SYN(同步)分節(jié)强挫,它告訴服務(wù)器將在(待建立的)連接中發(fā)送的數(shù)據(jù)的初始序列號(hào),通常SYN分節(jié)不攜帶數(shù)據(jù)薛躬,其所在IP數(shù)據(jù)報(bào)只含有一個(gè)IP首部俯渤、一個(gè)TCP首部及可能有的TCP選項(xiàng)
(3)服務(wù)器必須確認(rèn)(ACK)客戶的SYN,同時(shí)自己也得發(fā)送一個(gè)SYN分節(jié)型宝,他/她含有服務(wù)器將在同一連接中發(fā)送的數(shù)據(jù)的初始序列號(hào)八匠。服務(wù)器在單個(gè)分節(jié)中發(fā)送SYN和對(duì)客戶SYN的ACK(確認(rèn))
(4)客戶必須確認(rèn)服務(wù)器的SYN
這三種交換至少要三個(gè)分組,因此稱之為TCP的三路握手(three-way handshake)趴酣。
上圖給出的客戶的初始序列號(hào)為J梨树,服務(wù)器的初始序列號(hào)為K。ACK中的確定號(hào)是發(fā)送這個(gè)ACK的一端所期待的下一個(gè)序列號(hào)岖寞。因?yàn)镾YN占據(jù)一個(gè)字節(jié)的序列號(hào)空間抡四,所以每一個(gè)SYN的ACK中的確定號(hào)就是該SYN的初始序列號(hào)加1。類似地仗谆,每一個(gè)FIN(表示結(jié)束)的ACK中的確認(rèn)號(hào)為該FIN的序列號(hào)加1
建立TCP連接就好比一個(gè)電話系統(tǒng)指巡。socket函數(shù)等同于有電話可用。bind函數(shù)是在告訴別人你的電話號(hào)碼隶垮,這樣他們可以呼叫你藻雪。listen函數(shù)是打開電話振鈴,這樣當(dāng)有一個(gè)外來呼叫到達(dá)時(shí)狸吞,你就可以聽到阔涉。connect函數(shù)要求我們知道對(duì)方的電話號(hào)碼并撥打它。accept函數(shù)發(fā)生在被呼叫的人應(yīng)答電話之時(shí)捷绒。由accept返回客戶的標(biāo)識(shí)符(即客戶的IP地址和端口號(hào))類似于讓電話機(jī)的呼叫者ID功能部件顯示呼叫者的電話號(hào)碼瑰排。然而兩者的不同之處在于accept只在連接建立之后返回客戶的標(biāo)識(shí),而呼叫者ID功能部件卻在我們選擇應(yīng)答或不應(yīng)答電話之前顯示呼叫者的電話號(hào)碼暖侨。如果使用域名系統(tǒng)DNS椭住,它就提供一種類似于電話簿的服務(wù)。getaddrinfo類似于在電話薄中查找某個(gè)人的電話號(hào)碼字逗,getnameinfo則類似于有一本按照電話號(hào)碼而不是按照用戶名排序的電話薄京郑。