2.2 連接服務(wù)器
連接是什么意思
創(chuàng)建套接字之后,應(yīng)用程序(瀏覽器)就會調(diào)用connect,隨后協(xié)議棧會將本地的套接字與服務(wù)器的套接字進(jìn)行連接。
連接實(shí)際上是通信雙方交換控制信息,在套接字中記錄這些必要信息并準(zhǔn)備數(shù)據(jù)收發(fā)的一連串操作。
套接字剛剛創(chuàng)建完成的時候,里面并沒有存放任何數(shù)據(jù),也不知道通信的對象是誰。在這個狀態(tài)下,即便應(yīng)用程序要求發(fā)送數(shù)據(jù),協(xié)議棧也不知道數(shù)據(jù)應(yīng)該發(fā)送給誰。瀏覽器可以根據(jù)網(wǎng)址來查詢服務(wù)器的IP地址,而且根據(jù)規(guī)則也知道應(yīng)該使用80號端口,但只有瀏覽器知道這些必要的信息是不夠的,因?yàn)樵谡{(diào)用socket創(chuàng)建套接字時,這些信息并沒有傳遞給協(xié)議棧。因此,我們需要把服務(wù)器的IP地址和端口號等信息告知協(xié)議棧,這是連接操作的目的之一。
在服務(wù)器上,連應(yīng)用程序也不知道通信對象是誰,這樣下去永遠(yuǎn)也沒法開始通信。于是,我們需要讓客戶端向服務(wù)器告知必要的信息,比如“我想和你開始通信,我的IP地址是xxx.xxx. xxx.xxx,端口號是yyyy。”可見,客戶端向服務(wù)器傳達(dá)開始通信的請求,也是連接操作的目的之一。
連接實(shí)際上是通信雙方交換控制信息,在套接字中記錄這些必要信息并準(zhǔn)備數(shù)據(jù)收發(fā)的一連串操作,像上面提到的客戶端將IP地址和端口號告知服務(wù)器這樣的過程就屬于交換控制信息的一個具體的例子。
使用“連接”這個詞是有原因的。通信技術(shù)的歷史已經(jīng)有100多年,從通信技術(shù)誕生之初到幾年之前的很長一段時間內(nèi),電話技術(shù)一直都是主流。
而電話的操作過程分為三個階段:
(1)撥號與對方連接;
(2)通話;
(3)掛斷。
人們將電話的思路套用在現(xiàn)在的計(jì)算機(jī)網(wǎng)絡(luò)中了,所以也就自然而然地將通信開始之前的準(zhǔn)備操作稱為“連接”了。如果沒有這段歷史的話,說不定現(xiàn)在我們就不叫“連接”而是叫“準(zhǔn)備”了。因此,如果覺得“連接”這個詞聽起來有些怪,那么用“準(zhǔn)備”這個詞來替換也問題不大。
交換控制信息,在套接字中記錄這些必要信息并準(zhǔn)備數(shù)據(jù)收發(fā)的一連串操作,像上面提到的客戶端將IP地址和端口號告知服務(wù)器這樣的過程就屬于交換控制信息的一個具體的例子。
當(dāng)執(zhí)行數(shù)據(jù)收發(fā)操作時,我們還需要一塊用來臨時存放要收發(fā)的數(shù)據(jù)的內(nèi)存空間,這塊內(nèi)存空間稱為緩沖區(qū),它也是在連接操作的過程中分配的。
負(fù)責(zé)保存控制信息的頭部
通信操作中使用的控制信息分為兩類。
(1)頭部中記錄的信息
(2)套接字(協(xié)議棧中的內(nèi)存空間)中記錄的信息
- 第一類是客戶端和服務(wù)器相互聯(lián)絡(luò)時交換的控制信息。這些信息不僅連接時需要,包括數(shù)據(jù)收發(fā)和斷開連接操作在內(nèi),整個通信過程中都需要,這些內(nèi)容在TCP協(xié)議的規(guī)格中進(jìn)行了定義。
這些字段是固定的,在連接、收發(fā)、斷開等各個階段中,每次客戶端和服務(wù)器之間進(jìn)行通信時,都需要提供這些控制信息。
這些控制信息位于網(wǎng)絡(luò)包的開頭,因此被稱為頭部。此外,以太網(wǎng)和IP協(xié)議也有自己的控制信息,這些信息也叫頭部,為了避免各種不同的頭部發(fā)生混淆,我們一般會記作TCP頭部、以太網(wǎng)頭部[插圖]、IP頭部。
- 控制信息還有另外一類,那就是保存在套接字中,用來控制協(xié)議棧操作的信息。應(yīng)用程序傳遞來的信息以及從通信對象接收到的信息都會保存在這里,還有收發(fā)數(shù)據(jù)操作的執(zhí)行狀態(tài)等信息也會保存在這里,協(xié)議棧會根據(jù)這些信息來執(zhí)行每一步的操作。我們可以說,套接字的控制信息和協(xié)議棧的程序本身其實(shí)是一體的,因此,“協(xié)議棧具體需要哪些信息”會根據(jù)協(xié)議棧本身的實(shí)現(xiàn)方式不同而不同,但這并沒有什么問題。
連接操作的實(shí)際過程


connect(<描述符>, <服務(wù)器IP地址和端口號>, …)
- 首先,客戶端先創(chuàng)建一個包含表示開始數(shù)據(jù)收發(fā)操作的控制信息的頭部。
連接操作的第一步是在TCP模塊處創(chuàng)建表示連接控制信息的頭部。
通過TCP頭部中的發(fā)送方和接收方端口號可以找到要連接的套接字。
當(dāng)TCP頭部創(chuàng)建好之后,接下來TCP模塊會將信息傳遞給IP模塊并委托它進(jìn)行發(fā)送[插圖]。IP模塊執(zhí)行網(wǎng)絡(luò)包發(fā)送操作后,網(wǎng)絡(luò)包就會通過網(wǎng)絡(luò)到達(dá)服務(wù)器,然后服務(wù)器上的IP模塊會將接收到的數(shù)據(jù)傳遞給TCP模塊,服務(wù)器的TCP模塊根據(jù)TCP頭部中的信息找到端口號對應(yīng)的套接字,也就是說,從處于等待連接狀態(tài)的套接字中找到與TCP頭部中記錄的端口號相同的套接字就可以了。當(dāng)找到對應(yīng)的套接字之后,套接字中會寫入相應(yīng)的信息,并將狀態(tài)改為正在連接。
接下來,服務(wù)器TCP模塊會將TCP頭部傳遞給IP模塊,并委托IP模塊向客戶端返回響應(yīng)。
然后,網(wǎng)絡(luò)包就會返回到客戶端,通過IP模塊到達(dá)TCP模塊,并通過TCP頭部的信息確認(rèn)連接服務(wù)器的操作是否成功。如果SYN為1則表示連接成功,這時會向套接字中寫入服務(wù)器的IP地址、端口號等信息,同時還會將狀態(tài)改為連接完畢。到這里,客戶端的操作就已經(jīng)完成,但其實(shí)還剩下最后一個步驟。剛才服務(wù)器返回響應(yīng)時將ACK比特設(shè)置為1,相應(yīng)地,客戶端也需要將ACK比特設(shè)置為1并發(fā)回服務(wù)器,告訴服務(wù)器剛才的響應(yīng)包已經(jīng)收到。當(dāng)這個服務(wù)器收到這個返回包之后,連接操作才算全部完成。
現(xiàn)在,套接字就已經(jīng)進(jìn)入隨時可以收發(fā)數(shù)據(jù)的狀態(tài)了,大家可以認(rèn)為這時有一根管子把兩個套接字連接了起來。當(dāng)然,實(shí)際上并不存在這么一根管子,不過這樣想比較容易理解,網(wǎng)絡(luò)業(yè)界也習(xí)慣這樣來描述。這根管子,我們稱之為連接(connection、session)。只要數(shù)據(jù)傳輸過程在持續(xù),也就是在調(diào)用close斷開之前,連接是一直存在的。
建立連接之后,協(xié)議棧的連接操作就結(jié)束了,也就是說connect已經(jīng)執(zhí)行完畢,控制流程被交回到應(yīng)用程序。