Socket相關(guān)

報文段


報文段是指TCP/IP協(xié)議網(wǎng)絡(luò)傳輸過程中,起著路由導(dǎo)航作用

用以查詢各個網(wǎng)絡(luò)路由網(wǎng)段,ip地址,交換協(xié)議等ip數(shù)據(jù)包

報文段充當(dāng)整個tcp/ip協(xié)議數(shù)據(jù)包的導(dǎo)航路由功能

報文在傳輸過程中會不斷的封裝成組、包、幀來傳輸?shù)?/p>


傳輸協(xié)議


協(xié)議顧名思義,一種規(guī)定,約束

約定大于配置,在網(wǎng)絡(luò)傳輸中依然適用;網(wǎng)絡(luò)的傳輸流程是健壯的穩(wěn)定的,得益于基礎(chǔ)的協(xié)議構(gòu)成

簡單來說:A->B的傳輸數(shù)據(jù),B能識別,繁殖B->A的傳輸數(shù)據(jù)A也能識別,這就是協(xié)議


IP地址


"1.1.1.1": 為直接廣播地址,會向全網(wǎng)廣播UDP消息,但是一般會被路由器防火墻攔截

"255.255.255.255": 為受限廣播地址,會在局域網(wǎng)絡(luò)內(nèi)發(fā)送UDP消息


UDP

用戶數(shù)據(jù)報協(xié)議,基于報文的協(xié)議,而不是基于連接的協(xié)議

應(yīng)用場景:DNS TFTP SNMP

UDP包的最大長度

1.png

16位-> 2字節(jié) 存儲長度信息;2^16-1=65535;自身協(xié)議占用:32+32位=64位=8字節(jié)

所以最大數(shù)據(jù)長度:65535-8=65507 byte字節(jié)

UDP單播,廣播,多播


單播:點對點

廣播:給所有設(shè)備發(fā)送數(shù)據(jù)(例如:受限廣播地址,255.255.255.255)

  • C網(wǎng)廣播地址一般為:xxx.xxx.xxx.255(192.168.1.255)

多播(組播):給一組發(fā)送數(shù)據(jù)

  • D類IP地址為多播預(yù)留

2.png

廣播地址運算


IP;192.168.124.7

子網(wǎng)掩碼: 255.255.255.0

網(wǎng)絡(luò)地址: 192.168.124.0

廣播地址: 192.168.124.255


但是運算結(jié)果不是絕對的,如下:


如果子網(wǎng)掩碼是:255.255.255.192-> 11111111.11111111.11111111.11000000

則可劃分網(wǎng)段就是最后的一個字節(jié)的1數(shù)據(jù),即2*2=4個

四個網(wǎng)段為:0-63 64-127 128-191 n 192-255

IP:192.168.124.7歸屬于第一個網(wǎng)段,所以廣播地址就是該網(wǎng)段的
最后一個即192.168.124.63 ,網(wǎng)絡(luò)地址(是該網(wǎng)段第一個地址)
仍是192.168.124.0


廣播通信問題

3.png

如上圖,主機一位于第一個網(wǎng)段,主機二位于第二個網(wǎng)段,所以二者無法通信

協(xié)議

什么是協(xié)議

從應(yīng)?的?度出發(fā),協(xié)議可理解為“規(guī)則”,是數(shù)據(jù)傳輸和數(shù)據(jù)的解釋的規(guī)則。

假設(shè),A、B雙?欲傳輸?件。規(guī)定:

  • 第?次,傳輸?件名,接收?接收到?件名,應(yīng)答OK給傳輸?;
  • 第?次,發(fā)送?件的尺?,接收?接收到該數(shù)據(jù)再次應(yīng)答?個OK;
  • 第三次,傳輸?件內(nèi)容。同樣,接收?接收數(shù)據(jù)完成后應(yīng)答OK表示?件內(nèi)容接收成功

由此,?論A、B之間傳遞何種?件,都是通過三次數(shù)據(jù)傳輸來完成。A、B之間形成了?個最簡單的數(shù)據(jù)傳輸規(guī)則。雙?都按此規(guī)則發(fā)送、接收數(shù)據(jù)。A、B之間達成的這個相互遵守的規(guī)則即為協(xié)議。

這種僅在A、B之間被遵守的協(xié)議稱之為原始協(xié)議。當(dāng)此協(xié)議被更多的?采?,不斷的增加、改進、維護、完善。最終形成?個穩(wěn)定的、完整的?件傳輸協(xié)議,被?泛應(yīng)?于各種?件傳輸過程中。該協(xié)議就成為?個標(biāo)準(zhǔn)協(xié)議。最早的ftp協(xié)議就是由此衍??來。

TCP協(xié)議注重數(shù)據(jù)的傳輸。http協(xié)議著重于數(shù)據(jù)的解釋。

典型協(xié)議

傳輸層 常?協(xié)議有TCP/UDP協(xié)議。
應(yīng)?層 常?的協(xié)議有HTTP協(xié)議,F(xiàn)TP協(xié)議。
?絡(luò)層 常?協(xié)議有IP協(xié)議、ICMP協(xié)議、IGMP協(xié)議。
?絡(luò)接?層 常?協(xié)議有ARP協(xié)議、RARP協(xié)議。
TCP傳輸控制協(xié)議(Transmission Control Protocol)是?種?向連接的、可靠的、基于字節(jié)流的
傳輸層通信協(xié)議。
UDP?戶數(shù)據(jù)報協(xié)議(User Datagram Protocol)是OSI參考模型中?種?連接的傳輸層協(xié)議,
提供?向事務(wù)的簡單不可靠信息傳送服務(wù)。
HTTP超?本傳輸協(xié)議(Hyper Text Transfer Protocol)是互聯(lián)?上應(yīng)?最為?泛的?種?絡(luò)協(xié)
議。
FTP?件傳輸協(xié)議(File Transfer Protocol)
IP協(xié)議是因特?互聯(lián)協(xié)議(Internet Protocol)
ICMP協(xié)議是Internet控制報?協(xié)議(Internet Control Message Protocol)它是TCP/IP協(xié)議族的?個?協(xié)議,?于在IP主機、路由器之間傳遞控制消息。
IGMP協(xié)議是 Internet 組管理協(xié)議(Internet Group Management Protocol),是因特?協(xié)議家
族中的?個組播協(xié)議。該協(xié)議運?在主機和組播路由器之間。
ARP協(xié)議是正向地址解析協(xié)議(Address Resolution Protocol),通過已知的IP,尋找對應(yīng)主機
的MAC地址。
RARP是反向地址轉(zhuǎn)換協(xié)議,通過MAC地址確定IP地址。

分層模型

  • 物理層:

主要定義物理設(shè)備標(biāo)準(zhǔn),如?線的接?類型、光纖的接?類型、各種傳輸介質(zhì)的傳輸速率等。它的主要作?是傳輸?特流(就是由1、0轉(zhuǎn)化為電流強弱來進?傳輸,到達?的地后再轉(zhuǎn)化為1、0,也就是我們常說的數(shù)模轉(zhuǎn)換與模數(shù)轉(zhuǎn)換)。這?層的數(shù)據(jù)叫做?特。

  • 數(shù)據(jù)鏈路層:

定義了如何讓格式化數(shù)據(jù)以幀為單位進?傳輸,以及如何讓控制對物理介質(zhì)的訪問。這?層通常還提供錯誤檢測和糾正,以確保數(shù)據(jù)的可靠傳輸。如:串?通信中使?到的115200、 8、N、1

  • ?絡(luò)層:

在位于不同地理位置的?絡(luò)中的兩個主機系統(tǒng)之間提供連接和路徑選擇。Internet的發(fā)展使得從世界各站點訪問信息的?戶數(shù)??增加,??絡(luò)層正是管理這種連接的層。

  • 傳輸層:

定義了?些傳輸數(shù)據(jù)的協(xié)議和端?號(WWW端?80等),如:TCP(傳輸控制協(xié)議,傳輸效率低,可靠性強,?于傳輸可靠性要求?,數(shù)據(jù)量?的數(shù)據(jù)),UDP(?戶數(shù)據(jù)報協(xié)議,與TCP特性恰恰相反,?于傳輸可靠性要求不?,數(shù)據(jù)量?的數(shù)據(jù),如QQ聊天數(shù)據(jù)就是通過這種?式傳輸?shù)模V饕菍南聦咏邮盏臄?shù)據(jù)進?分段和傳輸,到達?的地址后再進?重組。常常把這?層數(shù)據(jù)叫做段。

  • 會話層:

通過傳輸層(端?號:傳輸端?與接收端?)建?數(shù)據(jù)傳輸?shù)耐?。主要在你的系統(tǒng)之間發(fā)起會話或者接受會話請求(設(shè)備之間需要互相認識可以是IP也可以是MAC或者是主機名)。

  • 表示層:

可確保?個系統(tǒng)的應(yīng)?層所發(fā)送的信息可以被另?個系統(tǒng)的應(yīng)?層讀取。例如,PC程序與另?臺計算機進?通信,其中?臺計算機使?擴展???進制交換碼(EBCDIC),?另?臺則使?美國信息交換標(biāo)準(zhǔn)碼(ASCII)來表示相同的字符。如有必要,表示層會通過使??種通格式來實現(xiàn)多種數(shù)據(jù)格式之間的轉(zhuǎn)換。

  • 應(yīng)?層

是最靠近?戶的OSI層。這?層為?戶的應(yīng)?程序(例如電?郵件、?件傳輸和終端仿真)提供?絡(luò)服務(wù)。

1.png

下圖模擬一個數(shù)據(jù)發(fā)送到接收一層層封包和解包的過程


01網(wǎng)絡(luò)數(shù)據(jù)傳輸.png

通信過程

2.jpg

TCP/IP通信過程

上圖對應(yīng)兩臺計算機在同??段中的情況,如果兩臺計算機在不同的?段中,那么數(shù)據(jù)從?臺計算機到另?臺計算機傳輸過程中要經(jīng)過?個或多個路由器,如下圖所示:


3.jpg

跨路由通信

鏈路層有以太?、令牌環(huán)?等標(biāo)準(zhǔn),鏈路層負責(zé)?卡設(shè)備的驅(qū)動、幀同步(即從?線上檢測到什么信號算作新幀的開始)、沖突檢測(如果檢測到?jīng)_突就?動重發(fā))、數(shù)據(jù)差錯校驗等?作。交換機是?作在鏈路層的?絡(luò)設(shè)備,可以在不同的鏈路層?絡(luò)之間轉(zhuǎn)發(fā)數(shù)據(jù)幀(?如?兆以太?和百兆以太?之間、以太?和令牌環(huán)?之間),由于不同鏈路層的幀格式不同,交換機要將進來的數(shù)據(jù)包拆掉鏈路層?部重新封裝之后再轉(zhuǎn)發(fā)。

?絡(luò)層的IP協(xié)議是構(gòu)成Internet的基礎(chǔ)。Internet上的主機通過IP地址來標(biāo)識,Inter-net上有?量路由器負責(zé)根據(jù)IP地址選擇合適的路徑轉(zhuǎn)發(fā)數(shù)據(jù)包,數(shù)據(jù)包從Internet上的源主機到?的主機往往要經(jīng)過?多個路由器。路由器是?作在第三層的?絡(luò)設(shè)備,同時兼有交換機的功能,可以在不同的鏈路層接?之間轉(zhuǎn)發(fā)數(shù)據(jù)包,因此路由器需要將進來的數(shù)據(jù)包拆掉?絡(luò)層和鏈路層兩層?部并重新封裝。IP協(xié)議不保證傳輸?shù)目煽啃?,?shù)據(jù)包在傳輸過程中可能丟失,可靠性可以在上層協(xié)議或應(yīng)?程序中提供?持。

?絡(luò)層負責(zé)點到點(ptop,point-to-point)的傳輸(這?的“點”指主機或路由器),?傳輸層負責(zé)端到端(etoe,end-to-end)的傳輸(這?的“端”指源主機和?的主機)。傳輸層可選擇TCP或UDP協(xié)議。

TCP是?種?向連接的、可靠的協(xié)議,有點像打電話,雙?拿起電話互通身份之后就建?了連接,然后說話就?了,這邊說的話那邊保證聽得到,并且是按說話的順序聽到的,說完話掛機斷開連接。也就是說TCP傳輸?shù)碾p?需要?先建?連接,之后由TCP協(xié)議保證數(shù)據(jù)收發(fā)的可靠性,丟失的數(shù)據(jù)包?動重發(fā),上層應(yīng)?程序收到的總是可靠的數(shù)據(jù)流,通訊之后關(guān)閉連接。UDP是?連接的傳輸協(xié)議,不保證可靠性,有點像寄信,信寫好放到郵筒?,既不能保證信件在郵遞過程中不會丟失,也不能保證信件寄送順序。使?UDP協(xié)議的應(yīng)?程序需要??完成丟包重發(fā)、消息排序等?作。

?的主機收到數(shù)據(jù)包后,如何經(jīng)過各層協(xié)議棧最后到達應(yīng)?程序呢?其過程如下圖所示:


4.jpg

以太?驅(qū)動程序?先根據(jù)以太??部中的“上層協(xié)議”字段確定該數(shù)據(jù)幀的有效載荷(payload,指除去協(xié)議?部之外實際傳輸?shù)臄?shù)據(jù))是IP、ARP還是RARP協(xié)議的數(shù)據(jù)報,然后交給相應(yīng)的協(xié)議處理。假如是IP數(shù)據(jù)報,IP協(xié)議再根據(jù)IP?部中的“上層協(xié)議”字段確定該數(shù)據(jù)報的有效載荷是TCP、
UDP、ICMP還是IGMP,然后交給相應(yīng)的協(xié)議處理。假如是TCP段或UDP段,TCP或UDP協(xié)議再根據(jù)TCP?部或UDP?部的“端?號”字段確定應(yīng)該將應(yīng)?層數(shù)據(jù)交給哪個?戶進程。IP地址是標(biāo)識?絡(luò)中不同主機的地址,?端?號就是同?臺主機上標(biāo)識不同進程的地址,IP地址和端?號合起來標(biāo)識?絡(luò)中唯?的進程。

雖然IP、ARP和RARP數(shù)據(jù)報都需要以太?驅(qū)動程序來封裝成幀,但是從功能上劃分,ARP和RARP屬于鏈路層,IP屬于?絡(luò)層。雖然ICMP、IGMP、TCP、UDP的數(shù)據(jù)都需要IP協(xié)議來封裝成數(shù)據(jù)報,但是從功能上劃分,ICMP、IGMP與IP同屬于?絡(luò)層,TCP和UDP屬于傳輸層。

02以太網(wǎng)幀格式.png

協(xié)議格式

數(shù)據(jù)包封裝

傳輸層及其以下的機制由內(nèi)核提供,應(yīng)?層由?戶進程提供(后?將介紹如何使?socket API編寫應(yīng)?程序),應(yīng)?程序?qū)νㄓ崝?shù)據(jù)的含義進?解釋,?傳輸層及其以下處理通訊的細節(jié),將數(shù)據(jù)從?臺計算機通過?定的路徑發(fā)送到另?臺計算機。應(yīng)?層數(shù)據(jù)通過協(xié)議棧發(fā)到?絡(luò)上時,每層協(xié)議都要加上?個數(shù)據(jù)?部(header),稱為封裝(Encapsulation),如下圖所示:


5.jpg

TCP/IP數(shù)據(jù)包封裝

不同的協(xié)議層對數(shù)據(jù)包有不同的稱謂,在傳輸層叫做段(segment),在?絡(luò)層叫做數(shù)據(jù)報(datagram),在鏈路層叫做幀(frame)。數(shù)據(jù)封裝成幀后發(fā)到傳輸介質(zhì)上,到達?的主機后每層協(xié)議再剝掉相應(yīng)的?部,最后將應(yīng)?層數(shù)據(jù)交給應(yīng)?程序處理。

以太網(wǎng)幀格式

6.jpg

以太?幀格式

其中的源地址和?的地址是指?卡的硬件地址(也叫MAC地址),?度是48位,是在?卡出?時固化的??稍趕hell中使?ifconfig命令查看,“HWaddr 00:15:F2:14:9E:3F”部分就是硬件地址。協(xié)議字段有三種值,分別對應(yīng)IP、ARP、RARP。幀尾是CRC校驗碼。以太?幀中的數(shù)據(jù)?度規(guī)定最?46字節(jié),最?1500字節(jié),ARP和RARP數(shù)據(jù)包的?度不夠46字節(jié),要在后?補填充位。最?值1500稱為以太?的最?傳輸單元(MTU),不同的?絡(luò)類型有不同的MTU,如果?個數(shù)據(jù)包從以太?路由到撥號鏈路上,數(shù)據(jù)包?度?于撥號鏈路的MTU,則需要對數(shù)據(jù)包進?分?(fragmentation)。ifconfig命令輸出中也有“MTU:1500”。注意,MTU這個概念指數(shù)據(jù)幀中有效載荷的最??度,不包括幀頭長度。

ARP數(shù)據(jù)報格式

在?絡(luò)通訊時,源主機的應(yīng)?程序知道?的主機的IP地址和端?號,卻不知道?的主機的硬件地址,?數(shù)據(jù)包?先是被?卡接收到再去處理上層協(xié)議的,如果接收到的數(shù)據(jù)包的硬件地址與本機不符,則直接丟棄。因此在通訊前必須獲得?的主機的硬件地址。ARP協(xié)議就起到這個作?。源主機發(fā)出ARP請求,詢問“IP地址是192.168.0.1的主機的硬件地址是多少”,并將這個請求?播到本地?段(以太?幀?部的硬件地址填FF:FF:FF:FF:FF:FF表示?播),?的主機接收到?播的ARP請求,發(fā)現(xiàn)其中的IP地址與本機相符,則發(fā)送?個ARP應(yīng)答數(shù)據(jù)包給源主機,將??的硬件地址填寫在應(yīng)答包中。

每臺主機都維護?個ARP緩存表,可以?arp-a命令查看。緩存表中的表項有過期時間(?般為20分鐘),如果20分鐘內(nèi)沒有再次使?某個表項,則該表項失效,下次還要發(fā)ARP請求來獲得?的主機的硬件地址。想?想,為什么表項要有過期時間?不是?直有效?

7.jpg

ARP數(shù)據(jù)報格式

源MAC地址、?的MAC地址在以太??部和ARP請求中各出現(xiàn)?次,對于鏈路層為以太?的情況是多余的,但如果鏈路層是其它類型的?絡(luò)則有可能是必要的。硬件類型指鏈路層?絡(luò)類型,1為以太?,協(xié)議類型指要轉(zhuǎn)換的地址類型,0x0800為IP地址,后?兩個地址?度對于以太?地址和IP地址分別為6和4(字節(jié)),op字段為1表示ARP請求,op字段為2表示ARP應(yīng)答。

看?個具體的例?。

請求幀如下(為了清晰在每?的前?加了字節(jié)計數(shù),每?16個字節(jié)):以太??部(14字節(jié))

0000: ff ff ff ff ff ff 00 05 5d 61 58 a8 08 06

ARP幀(28字節(jié))

0000: 00 01
0010: 08 00 06 04 00 01 00 05 5d 61 58 a8 c0 a8 00 37
0020: 00 00 00 00 00 00 c0 a8 00 02

填充位(18字節(jié))

0020: 00 77 31 d2 50 10
0030: fd 78 41 d3 00 00 00 00 00 00 00 00

以太??部:?的主機采??播地址,源主機的MAC地址是00:05:5d:61:58:a8,上層協(xié)議類型0x0806表示ARP。

ARP幀:硬件類型0x0001表示以太?,協(xié)議類型0x0800表示IP協(xié)議,硬件地址(MAC地址)?度為6,協(xié)議地址(IP地址)?度為4,op為0x0001表示請求?的主機的MAC地址,源主機MAC地址為00:05:5d:61:58:a8,源主機IP地址為c0 a8 00 37(192.168.0.55),?的主機MAC地址全0待填寫,?的主機IP地址為c0 a8 00 02(192.168.0.2)。

由于以太?規(guī)定最?數(shù)據(jù)?度為46字節(jié),ARP幀?度只有28字節(jié),因此有18字節(jié)填充位,填充位的內(nèi)容沒有定義,與具體實現(xiàn)相關(guān)。

應(yīng)答幀如下:

以太??部

0000: 00 05 5d 61 58 a8 00 05 5d a1 b8 40 08 06

ARP幀

0000: 00 01
0010: 08 00 06 04 00 02 00 05 5d a1 b8 40 c0 a8 00 02
0020: 00 05 5d 61 58 a8 c0 a8 00 37

填充位

0020: 00 77 31 d2 50 10
0030: fd 78 41 d3 00 00 00 00 00 00 00 00

以太??部:?的主機的MAC地址是00:05:5d:61:58:a8,源主機的MAC地址是
00:05:5d:a1:b8:40,上層協(xié)議類型0x0806表示ARP。

ARP幀:硬件類型0x0001表示以太?,協(xié)議類型0x0800表示IP協(xié)議,硬件地址(MAC地址)?度為6,協(xié)議地址(IP地址)?度為4,op為0x0002表示應(yīng)答,源主機MAC地址為00:05:5d:a1:b8:40,源主機IP地址為c0 a8 00 02(192.168.0.2),?的主機MAC地址為00:05:5d:61:58:a8,?的主機IP地址為c0 a8 00 37(192.168.0.55)

IP段格式

8.jpg

IP數(shù)據(jù)報格式

IP數(shù)據(jù)報的?部?度和數(shù)據(jù)?度都是可變?的,但總是4字節(jié)的整數(shù)倍。

對于IPv4,4位版本字段是4。4位?部?度的數(shù)值是以4字節(jié)為單位的,最?值為5,也就是說?部?度最?是4x5=20字節(jié),也就是不帶任何選項的IP?部,4位能表示的最?值是15,也就是說?部?度最?是60字節(jié)。

8位TOS字段有3個位?來指定IP數(shù)據(jù)報的優(yōu)先級(?前已經(jīng)廢棄不?),還有4個位表示可選的服務(wù)類型(最?延遲、最?吐量、最?可靠性、最?成本),還有?個位總是0???度是整個數(shù)據(jù)報(包括IP?部和IP層payload)的字節(jié)數(shù)。每傳?個IP數(shù)據(jù)報,16位的標(biāo)識加1,可?于分?和重新組裝數(shù)據(jù)報。3位標(biāo)志和13位?偏移?于分?。

TTL(Time to live)是這樣?的:源主機為數(shù)據(jù)包設(shè)定?個?存時間,?如64,每過?個路由器就把該值減1,如果減到0就表示路由已經(jīng)太?了仍然找不到?的主機的?絡(luò),就丟棄該包,因此這個?存時間的單位不是秒,?是跳(hop)。

協(xié)議字段指示上層協(xié)議是TCP、UDP、ICMP還是IGMP。然后是校驗和,只校驗IP?部,數(shù)據(jù)的校驗由更?層協(xié)議負責(zé)。IPv4的IP地址?度為32位。

03TCP.IP協(xié)議.png

UDP數(shù)據(jù)報格式

9.jpg

UDP數(shù)據(jù)段

下?分析?幀基于UDP的TFTP協(xié)議幀。

以太??部

0000: 00 05 5d 67 d0 b1 00 05 5d 61 58 a8 08 00

IP?部

0000: 45 00
0010: 00 53 93 25 00 00 80 11 25 ec c0 a8 00 37 c0 a8
0020: 00 01

UDP?部

0020: 05 d4 00 45 00 3f ac 40

TFTP協(xié)議

0020: 00 01 'c'':''\''q'
0030: 'w''e''r''q''.''q''w''e'00 'n''e''t''a''s''c''i'
0040: 'i'00 'b''l''k''s''i''z''e'00 '5''1''2'00 't''i'
0050: 'm''e''o''u''t'00 '1''0'00 't''s''i''z''e'00 '0'

以太??部:源MAC地址是00:05:5d:61:58:a8,?的MAC地址是00:05:5d:67:d0:b1,上層協(xié)議類型0x0800表示IP。

IP?部:每?個字節(jié)0x45包含4位版本號和4位?部?度,版本號為4,即IPv4,?部?度為5,說明IP?部不帶有選項字段。服務(wù)類型為0,沒有使?服務(wù)。16位總?度字段(包括IP?部和IP層payload的?度)為0x0053,即83字節(jié),加上以太??部14字節(jié)可知整個幀?度是97字節(jié)。IP報標(biāo)識是0x9325,標(biāo)志字段和?偏移字段設(shè)置為0x0000,就是DF=0允許分?,MF=0此數(shù)據(jù)報沒有更多分?,沒有分?偏移。TTL是0x80,也就是128。上層協(xié)議0x11表示UDP協(xié)議。IP?部校驗和為0x25ec,源主機IP是c0 a8 00 37(192.168.0.55),?的主機IP是c0 a8 00
01(192.168.0.1)。

UDP?部:源端?號0x05d4(1492)是客戶端的端?號,?的端?號0x0045(69)是TFTP服務(wù)的well-known端?號。UDP報?度為0x003f,即63字節(jié),包括UDP?部和UDP層pay-load的?度。UDP?部和UDP層payload的校驗和為0xac40。

TFTP是基于?本的協(xié)議,各字段之間?字節(jié)0分隔,開頭的00 01表示請求讀取?個?件,接下來的各字段是:

c:\qwerq.qwe
netascii
blksize 512
timeout 10
tsize 0

?般的?絡(luò)通信都是像TFTP協(xié)議這樣,通信的雙?分別是客戶端和服務(wù)器,客戶端主動發(fā)起請求(上?的例?就是客戶端發(fā)起的請求幀),?服務(wù)器被動地等待、接收和應(yīng)答請求??蛻舳说腎P地址和端?號唯?標(biāo)識了該主機上的TFTP客戶端進程,服務(wù)器的IP地址和端?號唯?標(biāo)識了該主機上的TFTP服務(wù)進程,由于客戶端是主動發(fā)起請求的??,它必須知道服務(wù)器的IP地址和TFTP服務(wù)進程的端?號,所以,?些常?的?絡(luò)協(xié)議有默認的服務(wù)器端?,例如HTTP服務(wù)默認TCP協(xié)議的80端?,F(xiàn)TP服務(wù)默認TCP協(xié)議的21端?,TFTP服務(wù)默認UDP協(xié)議的69端?(如上例所示)。
在使?客戶端程序時,必須指定服務(wù)器的主機名或IP地址,如果不明確指定端?號則采?默認端?,請讀者查閱ftp、tftp等程序的manpage了解如何指定端?號。/etc/services中列出了所有well-known的服務(wù)端?和對應(yīng)的傳輸層協(xié)議,這是由IANA(Internet Assigned NumbersAuthority)規(guī)定的,其中有些服務(wù)既可以?TCP也可以?UDP,為了清晰,IANA規(guī)定這樣的服務(wù)采?相同的TCP或UDP默認端?號,?另外?些TCP和UDP的相同端?號卻對應(yīng)不同的服務(wù)。很多服務(wù)有well-known的端?號,然?客戶端程序的端?號卻不必是well-known的,往往是每次運?客戶端程序時由系統(tǒng)?動分配?個空閑的端?號,?完就釋放掉,稱為ephemeral的端?號,想想這是為什么?

前?提過,UDP協(xié)議不?向連接,也不保證傳輸?shù)目煽啃?,例如?/p>

發(fā)送端的UDP協(xié)議層只管把應(yīng)?層傳來的數(shù)據(jù)封裝成段交給IP協(xié)議層就算完成任務(wù)了,如果因為?絡(luò)故障該段?法發(fā)到對?,UDP協(xié)議層也不會給應(yīng)?層返回任何錯誤信息。

接收端的UDP協(xié)議層只管把收到的數(shù)據(jù)根據(jù)端?號交給相應(yīng)的應(yīng)?程序就算完成任務(wù)了,如果發(fā)送端發(fā)來多個數(shù)據(jù)包并且在?絡(luò)上經(jīng)過不同的路由,到達接收端時順序已經(jīng)錯亂了,UDP協(xié)議層也不保證按發(fā)送時的順序交給應(yīng)?層。

通常接收端的UDP協(xié)議層將收到的數(shù)據(jù)放在?個固定??的緩沖區(qū)中等待應(yīng)?程序來提取和處理,如果應(yīng)?程序提取和處理的速度很慢,?發(fā)送端發(fā)送的速度很快,就會丟失數(shù)據(jù)包,UDP協(xié)議層并不報告這種錯誤。

因此,使?UDP協(xié)議的應(yīng)?程序必須考慮到這些可能的問題并實現(xiàn)適當(dāng)?shù)慕鉀Q?案,例如等待應(yīng)答、超時重發(fā)、為數(shù)據(jù)包編號、流量控制等。?般使?UDP協(xié)議的應(yīng)?程序?qū)崿F(xiàn)都?較簡單,只是發(fā)送?些對可靠性要求不?的消息,?不發(fā)送?量的數(shù)據(jù)。例如,基于UDP的TFTP協(xié)議?般只?于傳送??件(所以才叫trivial的ftp),?基于TCP的FTP協(xié)議適?于 各種?件的傳輸。TCP協(xié)議?是如何??向連接的服務(wù)來代替應(yīng)?程序解決傳輸?shù)目煽啃詥栴}呢。

TCP數(shù)據(jù)報格式

10.jpg

TCP數(shù)據(jù)段

與UDP協(xié)議?樣也有源端?號和?的端?號,通訊的雙?由IP地址和端?號標(biāo)識。32位序號、32位確認序號、窗???稍后詳細解釋。4位?部?度和IP協(xié)議頭類似,表示TCP協(xié)議頭的?度,以4字節(jié)為單位,因此TCP協(xié)議頭最?可以是4x15=60字節(jié),如果沒有選項字段,TCP協(xié)議頭最短20字節(jié)。URG、ACK、PSH、RST、SYN、FIN是六個控制位,本節(jié)稍后將解釋SYN、ACK、FIN、RST四個位,其它位的解釋從略。16位檢驗和將TCP協(xié)議頭和數(shù)據(jù)都計算在內(nèi)。緊急指針和各種選項的解釋從略。

TCP協(xié)議

TCP通信時序

下圖是?次TCP通訊的時序圖。TCP連接建?斷開。包含三次握?和四次握?。


11.jpg

TCP通訊時序

在這個例?中,?先客戶端主動發(fā)起連接、發(fā)送請求,然后服務(wù)器端響應(yīng)請求,然后客戶端主動關(guān)閉連接。兩條豎線表示通訊的兩端,從上到下表示時間的先后順序,注意,數(shù)據(jù)從?端傳到?絡(luò)的另?端也需要時間,所以圖中的箭頭都是斜的。雙?發(fā)送的段按時間順序編號為1-10,各段中的主要信息在箭頭上標(biāo)出,例如段2的箭頭上標(biāo)著SYN, 8000(0), ACK1001, ,表示該段中的SYN位置1,32位序號是8000,該段不攜帶有效載荷(數(shù)據(jù)字節(jié)數(shù)為0),ACK位置1,32位確認序號是1001,帶有?個mss(Maximum Segment Size,最?報??度)選項值為1024。

建?連接(三次握?)的過程:

  • 客戶端發(fā)送?個帶SYN標(biāo)志的TCP報?到服務(wù)器。這是三次握?過程中的段1

客戶端發(fā)出段1,SYN位表示連接請求。序號是1000,這個序號在?絡(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ā)來的段不要超過這個?度。

  • 服務(wù)器端回應(yīng)客戶端,是三次握?中的第2個報?段,同時帶ACK標(biāo)志和SYN標(biāo)志。它表示對剛才客戶端SYN的回應(yīng);同時?發(fā)送SYN給客戶端,詢問客戶端是否準(zhǔn)備好進?數(shù)據(jù)通訊。

服務(wù)器發(fā)出段2,也帶有SYN位,同時置ACK位表示確認,確認序號是1001,表示“我接收到序號1000及其以前所有的段,請你下次發(fā)送序號為1001的段”,也就是應(yīng)答了客戶端的連接請求,同時也給客戶端發(fā)出?個連接請求,同時聲明最?尺?為1024。

  • 客戶必須再次回應(yīng)服務(wù)器端?個ACK報?,這是報?段3。

客戶端發(fā)出段3,對服務(wù)器的連接請求進?應(yīng)答,確認序號是8001。在這個過程中,客戶端和服務(wù)器分別給對?發(fā)了連接請求,也應(yīng)答了對?的連接請求,其中服務(wù)器的請求和應(yīng)答在?個段中
發(fā)出,因此?共有三個段?于建?連接,稱為“三?握?(three-way-handshake)”。在建?連接的同時,雙?協(xié)商了?些信息,例如雙?發(fā)送序號的初始值、最?段尺?等。

在TCP通訊中,如果??收到另??發(fā)來的段,讀出其中的?的端?號,發(fā)現(xiàn)本機并沒有任何進程使?這個端?,就會應(yīng)答?個包含RST位的段給另??。例如,服務(wù)器并沒有任何進程使?8080端?,我們卻?telnet客戶端去連接它,服務(wù)器收到客戶端發(fā)來的SYN段就會應(yīng)答?個RST段,客戶端的telnet程序收到RST段后報告錯誤Connection refused:

$ telnet 192.168.0.200 8080
Trying 192.168.0.200...
telnet: Unable to connect to remote host: Connection refused

數(shù)據(jù)傳輸?shù)倪^程:

  • 客戶端發(fā)出段4,包含從序號1001開始的20個字節(jié)數(shù)據(jù)。
  • 服務(wù)器發(fā)出段5,確認序號為1021,對序號為1001-1020的數(shù)據(jù)表示確認收到,同時請求發(fā)送序號1021開始的數(shù)據(jù),服務(wù)器在應(yīng)答的同時也向客戶端發(fā)送從序號8001開始的10個字節(jié)數(shù)據(jù),這稱為piggyback。
  • 客戶端發(fā)出段6,對服務(wù)器發(fā)來的序號為8001-8010的數(shù)據(jù)表示確認收到,請求發(fā)送序號8011開始的數(shù)據(jù)。

在數(shù)據(jù)傳輸過程中,ACK和確認序號是?常重要的,應(yīng)?程序交給TCP協(xié)議發(fā)送的數(shù)據(jù)會暫存在TCP層的發(fā)送緩沖區(qū)中,發(fā)出數(shù)據(jù)包給對?之后,只有收到對?應(yīng)答的ACK段才知道該數(shù)據(jù)包確實發(fā)到了對?,可以從發(fā)送緩沖區(qū)中釋放掉了,如果因為?絡(luò)故障丟失了數(shù)據(jù)包或者丟失了對?發(fā)回的ACK段,經(jīng)過等待超時后TCP協(xié)議?動將發(fā)送緩沖區(qū)中的數(shù)據(jù)包重發(fā)。

關(guān)閉連接(四次握?)的過程:

由于TCP連接是全雙?的,因此每個?向都必須單獨進?關(guān)閉。這原則是當(dāng)??完成它的數(shù)據(jù)發(fā)送任務(wù)后就能發(fā)送?個FIN來終?這個?向的連接。收到?個FIN只意味著這??向上沒有數(shù)據(jù)流動,?個TCP連接在收到?個FIN后仍能發(fā)送數(shù)據(jù)。?先進?關(guān)閉的??將執(zhí)?主動關(guān)閉,?另??執(zhí)?被動關(guān)閉。

  • 客戶端發(fā)出段7,F(xiàn)IN位表示關(guān)閉連接的請求。
  • 服務(wù)器發(fā)出段8,應(yīng)答客戶端的關(guān)閉連接請求。
  • 服務(wù)器發(fā)出段9,其中也包含F(xiàn)IN位,向客戶端發(fā)送關(guān)閉連接請求。
  • 客戶端發(fā)出段10,應(yīng)答服務(wù)器的關(guān)閉連接請求.

建?連接的過程是三?握?,?關(guān)閉連接通常需要4個段,服務(wù)器的應(yīng)答和關(guān)閉連接請求通常不合并在?個段中,因為有連接半關(guān)閉的情況,這種情況下客戶端關(guān)閉連接之后就不能再發(fā)送數(shù)據(jù)給服務(wù)器了,但是服務(wù)器還可以發(fā)送數(shù)據(jù)給客戶端,直到服務(wù)器也關(guān)閉連接為?。

滑動窗? (TCP流量控制)

介紹UDP時描述了這樣的問題:如果發(fā)送端發(fā)送的速度較快,接收端接收到數(shù)據(jù)后處理的速度較慢,?接收緩沖區(qū)的??是固定的,就會丟失數(shù)據(jù)。TCP協(xié)議通過“滑動窗?(SlidingWindow)”機制解決這?問題??聪聢D的通訊過程


12.jpg

滑動窗?

  • 發(fā)送端發(fā)起連接,聲明最?段尺?是1460,初始序號是0,窗???是4K,表示“我的接收緩沖區(qū)還有4K字節(jié)空閑,你發(fā)的數(shù)據(jù)不要超過4K”。接收端應(yīng)答連接請求,聲明最?段尺?是1024,初始序號是8000,窗???是6K。發(fā)送端應(yīng)答,三?握?結(jié)束。
  • 發(fā)送端發(fā)出段4-9,每個段帶1K的數(shù)據(jù),發(fā)送端根據(jù)窗???知道接收端的緩沖區(qū)滿了,因此停?發(fā)送數(shù)據(jù)。
  • 接收端的應(yīng)?程序提?2K數(shù)據(jù),接收緩沖區(qū)?有了2K空閑,接收端發(fā)出段10,在應(yīng)答已收到6K數(shù)據(jù)的同時聲明窗???為2K。
  • 接收端的應(yīng)?程序?提?2K數(shù)據(jù),接收緩沖區(qū)有4K空閑,接收端發(fā)出段11,重新聲明窗???為4K。
  • 發(fā)送端發(fā)出段12-13,每個段帶2K數(shù)據(jù),段13同時還包含F(xiàn)IN位。
  • 接收端應(yīng)答接收到的2K數(shù)據(jù)(6145-8192),再加上FIN位占?個序號8193,因此應(yīng)答序號是8194,連接處于半關(guān)閉狀態(tài),接收端同時聲明窗???為2K。
  • 接收端的應(yīng)?程序提?2K數(shù)據(jù),接收端重新聲明窗???為4K。
  • 接收端的應(yīng)?程序提?剩下的2K數(shù)據(jù),接收緩沖區(qū)全空,接收端重新聲明窗???為6K。
  • 接收端的應(yīng)?程序在提?全部數(shù)據(jù)后,決定關(guān)閉連接,發(fā)出段17包含F(xiàn)IN位,發(fā)送端應(yīng)答,連接完全關(guān)閉。

上圖在接收端???塊表示1K數(shù)據(jù),實?的??塊表示已接收到的數(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ù),這?點和TCP是很不同的。

TCP狀態(tài)轉(zhuǎn)換

這個圖N多?都知道,它排除和定位?絡(luò)或系統(tǒng)故障時?有幫助,但是怎樣牢牢地將這張圖刻在腦中呢?那么你就?定要對這張圖的每?個狀態(tài),及轉(zhuǎn)換的過程有深刻的認識,不能只停留在?知半解之中。下?對這張圖的11種狀態(tài)詳細解析?下,以便加強記憶!不過在這之前,先回顧?下TCP建?連接的三次握?過程,以及 關(guān)閉連接的四次握?過程。

13.jpg

CLOSED:表示初始狀態(tài)。

LISTEN:該狀態(tài)表示服務(wù)器端的某個SOCKET處于監(jiān)聽狀態(tài),可以接受連接。

SYN_SENT:這個狀態(tài)與SYN_RCVD遙相呼應(yīng),當(dāng)客戶端SOCKET執(zhí)?CONNECT連接時,它?先發(fā)送SYN報?,隨即進?到了SYN_SENT狀態(tài),并等待服務(wù)端的發(fā)送三次握?中的第2個報?。SYN_SENT狀態(tài)表示客戶端已發(fā)送SYN報?。

SYN_RCVD: 該狀態(tài)表示接收到SYN報?,在正常情況下,這個狀態(tài)是服務(wù)器端的SOCKET在建?TCP連接時的三次握?會話過程中的?個中間狀態(tài),很短暫。此種狀態(tài)時,當(dāng)收到客戶端的ACK報?后,會進?到ESTABLISHED狀態(tài)。

ESTABLISHED:表示連接已經(jīng)建?。

FIN_WAIT_1: FIN_WAIT_1和FIN_WAIT_2狀態(tài)的真正含義都是表示等待對?的FIN報?。區(qū)別是:FIN_WAIT_1狀態(tài)是當(dāng)socket在ESTABLISHED狀態(tài)時,想主動關(guān)閉連接,向?qū)?發(fā)送了FIN報?,此時該socket進?到FIN_WAIT_1狀態(tài)。

FIN_WAIT_2狀態(tài)是當(dāng)對?回應(yīng)ACK后,該socket進?到FIN_WAIT_2狀態(tài),正常情況下,對?應(yīng)?上回應(yīng)ACK報?,所以FIN_WAIT_1狀態(tài)?般較難?到,?FIN_WAIT_2狀態(tài)可?netstat看到。

FIN_WAIT_2:主動關(guān)閉鏈接的??,發(fā)出FIN收到ACK以后進?該狀態(tài)。稱之為半連接或半關(guān)閉狀態(tài)。該狀態(tài)下的socket只能接收數(shù)據(jù),不能發(fā)。

TIME_WAIT: 表示收到了對?的FIN報?,并發(fā)送出了ACK報?,等2MSL后即可回到CLOSED可?狀態(tài)。如果FIN_WAIT_1狀態(tài)下,收到對?同時帶FIN標(biāo)志和ACK標(biāo)志的報?時,可以直接進?到TIME_WAIT狀態(tài),??須經(jīng)過FIN_WAIT_2狀態(tài)。

CLOSING: 這種狀態(tài)較特殊,屬于?種較罕?的狀態(tài)。正常情況下,當(dāng)你發(fā)送FIN報?后,按理來說是應(yīng)該先收到(或同時收到)對?的ACK報?,再收到對?的FIN報?。但是CLOSING狀態(tài)表示你發(fā)送FIN報?后,并沒有收到對?的ACK報?,反?卻也收到了對?的FIN報?。什么情況下會出現(xiàn)此種情況呢?如果雙??乎在同時close?個SOCKET的話,那么就出現(xiàn)了雙?同時發(fā)送FIN報?的情況,也即會出現(xiàn)CLOSING狀態(tài),表示雙?都正在關(guān)閉SOCKET連接。

CLOSE_WAIT: 此種狀態(tài)表示在等待關(guān)閉。當(dāng)對?關(guān)閉?個SOCKET后發(fā)送FIN報?給??,系統(tǒng)會回應(yīng)?個ACK報?給對?,此時則進?到CLOSE_WAIT狀態(tài)。接下來呢,察看是否還有數(shù)據(jù)發(fā)送給對?,如果沒有可以close這個SOCKET,發(fā)送FIN報?給對?,即關(guān)閉連接。所以在CLOSE_WAIT狀態(tài)下,需要關(guān)閉連接。

LAST_ACK: 該狀態(tài)是被動關(guān)閉??在發(fā)送FIN報?后,最后等待對?的ACK報?。當(dāng)收到ACK報?后,即可以進?到CLOSED可?狀態(tài)。

半關(guān)閉

當(dāng)TCP鏈接中A發(fā)送FIN請求關(guān)閉,B端回應(yīng)ACK后(A端進?FIN_WAIT_2狀態(tài)),B沒有?即發(fā)送FIN給A時,A?處在半鏈接狀態(tài),此時A可以接收B發(fā)送的數(shù)據(jù),但是A已不能再向B發(fā)送數(shù)據(jù)。

2MSL

2MSL (Maximum Segment Lifetime) TIME_WAIT狀態(tài)的存在有兩個理由:

  1. 讓4次握?關(guān)閉流程更加可靠;4次握?的最后?個ACK是是由主動關(guān)閉?發(fā)送出去的,若這個ACK丟失,被動關(guān)閉?會再次發(fā)?個FIN過來。若主動關(guān)閉?能夠保持?個2MSL的TIME_WAIT狀態(tài),則有更?的機會讓丟失的ACK被再次發(fā)送出去。
  2. 防?lost duplicate對后續(xù)新建正常鏈接的傳輸造成破壞。lost uplicate在實際的?絡(luò)中?常常?,經(jīng)常是由于路由器產(chǎn)?故障,路徑?法收斂,導(dǎo)致?個packet在路由器A,B,C之間做類似死循環(huán)的跳轉(zhuǎn)。IP頭部有個TTL,限制了?個包在?絡(luò)中的最?跳數(shù),因此這個包有兩種命運,要么最后TTL變?yōu)?,在?絡(luò)中消失;要么TTL在變?yōu)?之前路由器路徑收斂,它憑借剩余的TTL跳數(shù)終于到達?的地。但?常可惜的是TCP通過超時重傳機制在早些時候發(fā)送了?個跟它?模?樣的
    包,并先于它達到了?的地,因此它的命運也就注定被TCP協(xié)議棧拋棄。

另外?個概念叫做incarnation connection,指跟上次的socket pair?摸?樣的新連接,叫做incarnation of previous connection。lost uplicate加上incarnation connection,則會對我們的
傳輸造成致命的錯誤。

TCP是流式的,所有包到達的順序是不?致的,依靠序列號由TCP協(xié)議棧做順序的拼接;假設(shè)?個incarnation connection這時收到的seq=1000, 來了?個lost duplicate為seq=1000,len=1000,則TCP認為這個lost duplicate合法,并存放?了receive buffer,導(dǎo)致傳輸出現(xiàn)錯誤。通過?個
2MSL TIME_WAIT狀態(tài),確保所有的lost duplicate都會消失掉,避免對新連接造成錯誤。

該狀態(tài)為什么設(shè)計在主動關(guān)閉這??:

(1)發(fā)最后ACK的是主動關(guān)閉??。

(2)只要有??保持TIME_WAIT狀態(tài),就能起到避免incarnation connection在2MSL內(nèi)的重新建?,不需要兩?都有。
如何正確對待2MSL TIME_WAIT?RFC要求socket pair在處于TIME_WAIT時,不能再起?個incarnation connection。但絕?部分
TCP實現(xiàn),強加了更為嚴格的限制。在2MSL等待期間,socket中使?的本地端?在默認情況下不能再被使?。

若A 10.234.5.5 : 1234和B 10.55.55.60 : 6666建?了連接,A主動關(guān)閉,那么在A端只要port為
1234,?論對?的port和ip是什么,都不允許再起服務(wù)。這甚??RFC限制更為嚴格,RFC僅僅是要求socket pair不?致,?實現(xiàn)當(dāng)中只要這個port處于TIME_WAIT,就不允許起連接。這個限制
對主動打開?來說是?所謂的,因為?般?的是臨時端?;但對于被動打開?,?般是server,就悲劇了,因為server?般是熟知端?。?如http,?般端?是80,不可能允許這個服務(wù)在2MSL內(nèi)不能起來。
解決?案是給服務(wù)器的socket設(shè)置SO_REUSEADDR選項,這樣的話就算熟知端?處于TIME_WAIT狀態(tài),在這個端?上依舊可以將服務(wù)啟動。當(dāng)然,雖然有了SO_REUSEADDR選項,但sockt pair這個限制依舊存在。?如上?的例?,A通過SO_REUSEADDR選項依舊在1234端?上起了監(jiān)聽,但這時我們?nèi)羰菑腂通過6666端?去連它,TCP協(xié)議會告訴我們連接失敗,原因為Address already in use.
RFC 793中規(guī)定MSL為2分鐘,實際應(yīng)?中常?的是30秒,1分鐘和2分鐘等。
RFC (Request For Comments),是?系列以編號排定的?件。收集了有關(guān)因特?相關(guān)資訊,以及UNIX和因特?社群的軟件?件。

粘包拆包發(fā)生的原因

產(chǎn)生原因主要有這3種:滑動窗口、MSS/MTU限制、Nagle算法

  1. 滑動窗口
    TCP流量控制主要使用滑動窗口協(xié)議,滑動窗口是接受數(shù)據(jù)端使用的窗口大小,用來告訴發(fā)送端接收端的緩存大小,以此可以控制發(fā)送端發(fā)送數(shù)據(jù)的大小,從而達到流量

控制的目的。這個窗口大小就是我們一次傳輸幾個數(shù)據(jù)。對所有數(shù)據(jù)幀按順序賦予編號,發(fā)送方在發(fā)送過程中始終保持著一個發(fā)送窗口,只有落在發(fā)送窗口內(nèi)的幀才允許被發(fā)送;

同時接收方也維持著一個接收窗口,只有落在接收窗口內(nèi)的幀才允許接收。這樣通過調(diào)整發(fā)送方窗口和接收方窗口的大小可以實現(xiàn)流量控制。

現(xiàn)在來看一下滑動窗口是如何造成粘包、拆包的?

粘包:假設(shè)發(fā)送方的每256 bytes表示一個完整的報文,接收方由于數(shù)據(jù)處理不及時,這256個字節(jié)的數(shù)據(jù)都會被緩存到SO_RCVBUF(接收緩存區(qū))中。如果接收方的SO_RCVBUF中緩存了多個報文,那么對于接收方而言,這就是粘包。

拆包:考慮另外一種情況,假設(shè)接收方的窗口只剩了128,意味著發(fā)送方最多還可以發(fā)送128字節(jié),而由于發(fā)送方的數(shù)據(jù)大小是256字節(jié),因此只能發(fā)送前128字節(jié),等到接收方ack后,才能發(fā)送剩余字節(jié)。這就造成了拆包。

  1. MSS和MTU分片
    MSS: 是Maximum Segement Size縮寫,表示TCP報文中data部分的最大長度,是TCP協(xié)議在OSI五層網(wǎng)絡(luò)模型中傳輸層對一次可以發(fā)送的最大數(shù)據(jù)的限制。
    MTU: 最大傳輸單元是Maxitum Transmission Unit的簡寫,是OSI五層網(wǎng)絡(luò)模型中鏈路層(datalink layer)對一次可以發(fā)送的最大數(shù)據(jù)的限制。
    當(dāng)需要傳輸?shù)臄?shù)據(jù)大于MSS或者MTU時,數(shù)據(jù)會被拆分成多個包進行傳輸。由于MSS是根據(jù)MTU計算出來的,因此當(dāng)發(fā)送的數(shù)據(jù)滿足MSS時,必然滿足MTU。

MTU是以太網(wǎng)傳輸數(shù)據(jù)方面的限制,每個以太網(wǎng)幀都有最小的大小64bytes最大不能超過1518bytes。刨去以太網(wǎng)幀的幀頭 (DMAC目的MAC地址48bit=6Bytes+SMAC源MAC地址48bit=6Bytes+Type域2bytes)14Bytes和幀尾 CRC校驗部分4Bytes(這個部分有時候大家也把它叫做FCS),那么剩下承載上層協(xié)議的地方也就是Data域最大就只能有1500Bytes這個值 我們就把它稱之為MTU。
由于MTU限制了一次最多可以發(fā)送1500個字節(jié),而TCP協(xié)議在發(fā)送DATA時,還會加上額外的TCP Header和Ip Header,因此刨去這兩個部分,就是TCP協(xié)議一次可以發(fā)送的實際應(yīng)用數(shù)據(jù)的最大大小,也就是MSS。

  MSS長度=MTU長度-IP Header-TCP Header

TCP Header的長度是20字節(jié),IPv4中IP Header長度是20字節(jié),IPV6中IP Header長度是40字節(jié),因此:在IPV4中,以太網(wǎng)MSS可以達到1460byte;在IPV6中,以太網(wǎng)MSS可以達到1440byte。
需要注意的是MSS表示的一次可以發(fā)送的DATA的最大長度,而不是DATA的真實長度。發(fā)送方發(fā)送數(shù)據(jù)時,當(dāng)SO_SNDBUF中的數(shù)據(jù)量大于MSS時,操作系統(tǒng)會將數(shù)據(jù)進行拆分,使得每一部分都小于MSS,這就是拆包,然后每一部分都加上TCP Header,構(gòu)成多個完整的TCP報文進行發(fā)送,當(dāng)然經(jīng)過網(wǎng)絡(luò)層和數(shù)據(jù)鏈路層的時候,還會分別加上相應(yīng)的內(nèi)容。

需要注意: 默認情況下,與外部通信的網(wǎng)卡的MTU大小是1500個字節(jié)。而本地回環(huán)地址的MTU大小為65535,這是因為本地測試時數(shù)據(jù)不需要走網(wǎng)卡,所以不受到1500的限制。

3、 Nagle算法
TCP/IP協(xié)議中,無論發(fā)送多少數(shù)據(jù),總是要在數(shù)據(jù)(DATA)前面加上協(xié)議頭(TCP Header+IP Header),同時,對方接收到數(shù)據(jù),也需要發(fā)送ACK表示確認。

即使從鍵盤輸入的一個字符,占用一個字節(jié),可能在傳輸上造成41字節(jié)的包,其中包括1字節(jié)的有用信息和40字節(jié)的首部數(shù)據(jù)。這種情況轉(zhuǎn)變成了4000%的消耗,這樣的情況對于重負載的網(wǎng)絡(luò)來是無法接受的。

為了盡可能的利用網(wǎng)絡(luò)帶寬,TCP總是希望盡可能的發(fā)送足夠大的數(shù)據(jù)。(一個連接會設(shè)置MSS參數(shù),因此,TCP/IP希望每次都能夠以MSS尺寸的數(shù)據(jù)塊來發(fā)送數(shù)據(jù))。

Nagle算法就是為了盡可能發(fā)送大塊數(shù)據(jù),避免網(wǎng)絡(luò)中充斥著許多小數(shù)據(jù)塊。

Nagle算法的基本定義是任意時刻,最多只能有一個未被確認的小段。 所謂“小段”,指的是小于MSS尺寸的數(shù)據(jù)塊,所謂“未被確認”,是指一個數(shù)據(jù)塊發(fā)送出去后,沒有收到對方發(fā)送的ACK確認該數(shù)據(jù)已收到。
Nagle算法的規(guī)則:

  1)如果SO_SNDBUF(發(fā)送緩沖區(qū))中的數(shù)據(jù)長度達到MSS,則允許發(fā)送;

  2)如果該SO_SNDBUF中含有FIN,表示請求關(guān)閉連接,則先將SO_SNDBUF中的剩余數(shù)據(jù)發(fā)送,再關(guān)閉;
  3)設(shè)置了TCP_NODELAY=true選項,則允許發(fā)送。TCP_NODELAY是取消TCP的確認延遲機制,相當(dāng)于禁用了Nagle 算法。

  4)未設(shè)置TCP_CORK選項時,若所有發(fā)出去的小數(shù)據(jù)包(包長度小于MSS)均被確認,則允許發(fā)送;

  5)上述條件都未滿足,但發(fā)生了超時(一般為200ms),則立即發(fā)送。

總結(jié):UDP無粘包拆遷現(xiàn)象,最多會出現(xiàn)丟包問題,因為是不可靠通信方式; Nagle的算法通常會在TCP程序里添加兩行代碼,在未確認數(shù)據(jù)發(fā)送的時候讓發(fā)送器把數(shù)據(jù)送到緩存里。任何數(shù)據(jù)隨后繼續(xù)直到得到明顯的數(shù)據(jù)確認或者直到攢到了一定數(shù)量的數(shù)據(jù)了再發(fā)包。降低網(wǎng)絡(luò)負載

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容