Linux C高级编程——网络编程之TCP(3)
Linux網(wǎng)絡(luò)編程(三)——TCP
宗旨:技術(shù)的學(xué)習(xí)是有限的,分享的精神是無限的。
1、TCP段格式
? ? ? ? 和UDP協(xié)議一樣也有源端口號和目的端口號,通訊的雙方由IP地址和端口號標(biāo)識。32位序號、32位確認(rèn)序號、窗口大小。4位首部長度和IP協(xié)議頭類似,表示TCP協(xié)議頭的長度,以4字節(jié)為單位,因此TCP協(xié)議頭最長可以是4x15=60字節(jié),如果沒有選項(xiàng)字段,?TCP協(xié)議頭最短20字節(jié)。URG、?ACK、?PSH、?RST、?SYN、?FIN是六個控制位,本節(jié)稍后將解釋SYN、?ACK、?FIN、?RST四個位,其它位的解釋從略。16位檢驗(yàn)和將TCP協(xié)議頭和數(shù)據(jù)都計(jì)算在內(nèi)。
2、通訊時序——“三次握手,四次揮手”
? ? ? ? 首先客戶端主動發(fā)起連接、發(fā)送請求,然后服務(wù)器端響應(yīng)請求,然后客戶端主動關(guān)閉連接。兩條豎線表示通訊的兩端,從上到下表示時間的先后順序,注意,數(shù)據(jù)從一端傳到網(wǎng)絡(luò)的另一端也需要時間,所以圖中的箭頭都是斜的。雙方發(fā)送的段按時間順序編號為1-10,各段中的主要信息在箭頭上標(biāo)出,例如段2的箭頭上標(biāo)著SYN,?8000(0),?ACK?1001,?<mss?1024>,表示該段中的SYN位置1,32位序號是8000,該段不攜帶有效載荷(數(shù)據(jù)字節(jié)數(shù)為0),ACK位置1,32位確認(rèn)序號是1001,帶有一個mss選項(xiàng)值為1024。
建立連接的過程:
1.?客戶端發(fā)出段1,?SYN位表示連接請求。序號是1000,這個序號在網(wǎng)絡(luò)通訊中用作臨時的地址,每發(fā)一個數(shù)據(jù)字節(jié),這個序號要加1,這樣在接收端可以根據(jù)序號排出數(shù)據(jù)包的正確順序,也可以發(fā)現(xiàn)丟包的情況,另外,規(guī)定SYN位和FIN位也要占一個序號,這次雖然沒發(fā)數(shù)據(jù),但是由于發(fā)了SYN位,因此下次再發(fā)送應(yīng)該用序號1001。?mss表示最大段尺寸,如果一個段太大,封裝成幀后超過了鏈路層的最大幀長度,就必須在IP層分片,為了避免這種情況,客戶端聲明自己的最大段尺寸,建議服務(wù)器端發(fā)來的段不要超過這個長度。
2.?服務(wù)器發(fā)出段2,也帶有SYN位,同時置ACK位表示確認(rèn),確認(rèn)序號是1001,表示“我接收到序號1000及其以前所有的段,請你下次發(fā)送序號為1001的段”,也就是應(yīng)答了客戶端的連接請求,同時也給客戶端發(fā)出一個連接請求,同時聲明最大尺寸為1024。
3.?客戶端發(fā)出段3,對服務(wù)器的連接請求進(jìn)行應(yīng)答,確認(rèn)序號是8001。
? ? ? ? 客戶端和服務(wù)器分別給對方發(fā)了連接請求,也應(yīng)答了對方的連接請求,其中服務(wù)器的請求和應(yīng)答在一個段中發(fā)出,因此一共有三個段用于建立連接,稱為'''三方握手(?three-wayhandshake)?'''。在建立連接的同時,雙方協(xié)商了一些信息,例如雙方發(fā)送序號的初始值、最大段尺寸等。
? ? ? ? 在TCP通訊中,如果一方收到另一方發(fā)來的段,讀出其中的目的端口號,發(fā)現(xiàn)本機(jī)并沒有任何進(jìn)程使用這個端口,就會應(yīng)答一個包含RST位的段給另一方。
數(shù)據(jù)傳輸?shù)倪^程:
1、客戶端發(fā)出段4,包含從序號1001開始的20個字節(jié)數(shù)據(jù)。
2、服務(wù)器發(fā)出段5,確認(rèn)序號為1021,對序號為1001-1020的數(shù)據(jù)表示確認(rèn)收到,同時請求發(fā)送序號1021開始的數(shù)據(jù),服務(wù)器在應(yīng)答的同時也向客戶端發(fā)送從序號8001開始的10個字節(jié)數(shù)據(jù),這稱為piggyback。
3、客戶端發(fā)出段6,對服務(wù)器發(fā)來的序號為8001-8010的數(shù)據(jù)表示確認(rèn)收到,請求發(fā)送序號8011開始的數(shù)據(jù)。
? ? ? ? 在數(shù)據(jù)傳輸過程中,?ACK和確認(rèn)序號是非常重要的,應(yīng)用程序交給TCP協(xié)議發(fā)送的數(shù)據(jù)會暫存在TCP層的發(fā)送緩沖區(qū)中,發(fā)出數(shù)據(jù)包給對方之后,只有收到對方應(yīng)答的ACK段才知道該數(shù)據(jù)包確實(shí)發(fā)到了對方,可以從發(fā)送緩沖區(qū)中釋放掉了,如果因?yàn)榫W(wǎng)絡(luò)故障丟失了數(shù)據(jù)包或者丟失了對方發(fā)回的ACK段,經(jīng)過等待超時后TCP協(xié)議自動將發(fā)送緩沖區(qū)中的數(shù)據(jù)包重發(fā)。
關(guān)閉連接的過程:
1.?客戶端發(fā)出段7,?FIN位表示關(guān)閉連接的請求。
2.?服務(wù)器發(fā)出段8,應(yīng)答客戶端的關(guān)閉連接請求。
3.?服務(wù)器發(fā)出段9,其中也包含FIN位,向客戶端發(fā)送關(guān)閉連接請求。4.?客戶端發(fā)出段10,應(yīng)答服務(wù)器的關(guān)閉連接請求。
? ? ? ? 建立連接的過程是三方握手,而關(guān)閉連接通常需要4個段,服務(wù)器的應(yīng)答和關(guān)閉連接請求通常不合并在一個段中,因?yàn)橛羞B接半關(guān)閉的情況,這種情況下客戶端關(guān)閉連接之后就不能再發(fā)送數(shù)據(jù)給服務(wù)器了,但是服務(wù)器還可以發(fā)送數(shù)據(jù)給客戶端,直到服務(wù)器也關(guān)閉連接為止。
3、流量控制
? ? ? ? 如果發(fā)送端發(fā)送的速度較快,接收端接收到數(shù)據(jù)后處理的速度較慢,而接收緩沖區(qū)的大小是固定的,就會丟失數(shù)據(jù)。TCP協(xié)議通過'''滑動窗口(SlidingWindow)?'''機(jī)制解決這一問題。
1.?發(fā)送端發(fā)起連接,聲明最大段尺寸是1460,初始序號是0,窗口大小是4K,表示“我的接收緩沖區(qū)還有4K字節(jié)空閑,你發(fā)的數(shù)據(jù)不要超過4K”。接收端應(yīng)答連接請求,聲明最大段尺寸是1024,初始序號是8000,窗口大小是6K。發(fā)送端應(yīng)答,三方握手結(jié)束。
2.?發(fā)送端發(fā)出段4-9,每個段帶1K的數(shù)據(jù),發(fā)送端根據(jù)窗口大小知道接收端的緩沖區(qū)滿了,因此停止發(fā)送數(shù)據(jù)。
3.?接收端的應(yīng)用程序提走2K數(shù)據(jù),接收緩沖區(qū)又有了2K空閑,接收端發(fā)出段10,在應(yīng)答已收到6K數(shù)據(jù)的同時聲明窗口大小為2K。
4.?接收端的應(yīng)用程序又提走2K數(shù)據(jù),接收緩沖區(qū)有4K空閑,接收端發(fā)出段11,重新聲明窗口大小為4K。
5.?發(fā)送端發(fā)出段12-13,每個段帶2K數(shù)據(jù),段13同時還包含FIN位。
6.?接收端應(yīng)答接收到的2K數(shù)據(jù)(?6145-8192),再加上FIN位占一個序號8193,因此應(yīng)答序號是8194,連接處于半關(guān)閉狀態(tài),接收端同時聲明窗口大小為2K。
7.?接收端的應(yīng)用程序提走2K數(shù)據(jù),接收端重新聲明窗口大小為4K。
8.?接收端的應(yīng)用程序提走剩下的2K數(shù)據(jù),接收緩沖區(qū)全空,接收端重新聲明窗口大小為6K。
9.?接收端的應(yīng)用程序在提走全部數(shù)據(jù)后,決定關(guān)閉連接,發(fā)出段17包含FIN位,發(fā)送端應(yīng)答,連接完全關(guān)閉。
? ? ? ? 上圖在接收端用小方塊表示1K數(shù)據(jù),實(shí)心的小方塊表示已接收到的數(shù)據(jù),虛線框表示接收緩沖區(qū),因此套在虛線框中的空心小方塊表示窗口大小,從圖中可以看出,隨著應(yīng)用程序提走數(shù)據(jù),虛線框是向右滑動的,因此稱為滑動窗口。
? ? ? ? 發(fā)送端是一K一K地發(fā)送數(shù)據(jù),而接收端的應(yīng)用程序可以兩K兩K地提走數(shù)據(jù),當(dāng)然也有可能一次提走3K或6K數(shù)據(jù),或者一次只提走幾個字節(jié)的數(shù)據(jù),也就是說,應(yīng)用程序所看到的數(shù)據(jù)是一個整體,或說是一個流(?stream),在底層通訊中這些數(shù)據(jù)可能被拆成很多數(shù)據(jù)包來發(fā)送,但是一個數(shù)據(jù)包有多少字節(jié)對應(yīng)用程序是不可見的,因此TCP協(xié)議是面向流的協(xié)議。而UDP是面向消息的協(xié)議,每個UDP段都是一條消息,應(yīng)用程序必須以消息為單位提取數(shù)據(jù),不能一次提取任意字節(jié)的數(shù)據(jù),這一點(diǎn)和TCP是很不同的。
總結(jié)
以上是生活随笔為你收集整理的Linux C高级编程——网络编程之TCP(3)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2021年初行政区划数据
- 下一篇: Linux下打印调试管理