国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議

這篇具有很好參考價值的文章主要介紹了HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。


計算機網(wǎng)絡(luò)基礎(chǔ)

OSI模型定義了網(wǎng)絡(luò)互連的七層框架(物理層、數(shù)據(jù)鏈路層、網(wǎng)絡(luò)層、傳輸層、會話層、表示層、應(yīng)用層),每一層實現(xiàn)各自的功能和協(xié)議,并完成與相鄰層的接口通信。OSI模型各層的通信協(xié)議,大致舉例如下表所示:

層次 常見協(xié)議
應(yīng)用層 HTTP、SMTP、SNMP、FTP、Telnet、SIP、SSH、NFS、RTSP、XMPP、Whois、ENRP、等等
表示層 XDR、ASN.1、SMB、AFP、NCP、等等
會話層 ASAP、SSH、RPC、NetBIOS、ASP、Winsock、BSD Sockets、等等
傳輸層 TCP、UDP、TLS、RTP、SCTP、SPX、ATP、IL、等等
網(wǎng)絡(luò)層 IP、ICMP、IGMP、IPX、BGP、OSPF、RIP、IGRP、EIGRP、ARP、RARP、X.25、等等
數(shù)據(jù)鏈路層 以太網(wǎng)、令牌環(huán)、HDLC、幀中繼、ISDN、ATM、IEEE 802.11、FDDI、PPP、等等
物理層 例如銅纜、網(wǎng)線、光纜、無線電等等

HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),網(wǎng)絡(luò)協(xié)議,http,udp

基于TCP/IP的參考模型將協(xié)議分成四個層次,它們分別是鏈路層、網(wǎng)絡(luò)層、傳輸層和應(yīng)用層。下圖表示TCP/IP模型與OSI模型各層的對照關(guān)系。

HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),網(wǎng)絡(luò)協(xié)議,http,udp

TCP/IP協(xié)議族按照層次由上到下,層層包裝。最上面的是應(yīng)用層,這里面有http,ftp,等等我們熟悉的協(xié)議。而第二層則是傳輸層,著名的TCP和UDP協(xié)議就在這個層次。第三層是網(wǎng)絡(luò)層,IP協(xié)議就在這里,它負(fù)責(zé)對數(shù)據(jù)加上IP地址和其他的數(shù)據(jù)以確定傳輸?shù)哪繕?biāo)。第四層是數(shù)據(jù)鏈路層,這個層次為待傳送的數(shù)據(jù)加入一個以太網(wǎng)協(xié)議頭,并進(jìn)行CRC編碼,為最后的數(shù)據(jù)傳輸做準(zhǔn)備。

HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),網(wǎng)絡(luò)協(xié)議,http,udp

入棧的過程,數(shù)據(jù)發(fā)送方每層不斷地封裝首部與尾部,添加一些傳輸?shù)男畔?,確保能傳輸?shù)侥康牡?。出棧的過程,數(shù)據(jù)接收方每層不斷地拆除首部與尾部,得到最終傳輸?shù)臄?shù)據(jù)。

HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),網(wǎng)絡(luò)協(xié)議,http,udp

全雙工:一條鏈路,雙向通信。
舉個例子:間諜
通常抓到一個間諜,都會對其進(jìn)行拷問。
說:你的上級是誰?平時是怎么聯(lián)系的?
間諜:我和他認(rèn)識,知道彼此身份,并且有相互聯(lián)系的方式。
??????他是xxx,聯(lián)系方式xxxxxx。所以別再打我,作用不大,因為我都會說。

半雙工:一條鏈路,單向通信。
舉個例子:間諜
通常抓到一個間諜,都會對其進(jìn)行拷問。
說:你的上級是誰?平時是怎么聯(lián)系的?
間諜:我和上級是單向通信的,他聯(lián)系到我,我聯(lián)系不到他。所以別再打我,作用不大。

HTTP

HTTP協(xié)議通常承載于TCP協(xié)議之上,有時也承載于TLS或SSL協(xié)議層之上,這個時候,就成了我們常說的HTTPS。如下圖所示:

HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),網(wǎng)絡(luò)協(xié)議,http,udp
默認(rèn)HTTP的端口號為80,HTTPS的端口號為443。

HTTP協(xié)議永遠(yuǎn)都是客戶端發(fā)起請求,服務(wù)器回送響應(yīng)。這樣就限制了使用HTTP協(xié)議,無法實現(xiàn)在客戶端沒有發(fā)起請求的時候,服務(wù)器將消息推送給客戶端。
HTTP協(xié)議是一個無狀態(tài)的協(xié)議,同一個客戶端的這次請求和上次請求是沒有對應(yīng)關(guān)系。

工作流程

一次HTTP操作稱為一個事務(wù),其工作過程可分為四步:

1)首先客戶機與服務(wù)器需要建立連接。只要單擊某個超級鏈接,HTTP的工作開始。

2)建立連接后,客戶機發(fā)送一個請求給服務(wù)器,請求方式的格式為:統(tǒng)一資源標(biāo)識符(URL)、協(xié)議版本號,后邊是MIME信息包括請求修飾符、客戶機信息和可能的內(nèi)容。

3)服務(wù)器接到請求后,給予相應(yīng)的響應(yīng)信息,其格式為一個狀態(tài)行,包括信息的協(xié)議版本號、一個成功或錯誤的代碼,后邊是MIME信息包括服務(wù)器信息、實體信息和可能的內(nèi)容。

4)客戶端接收服務(wù)器所返回的信息通過瀏覽器顯示在用戶的顯示屏上,然后客戶機與服務(wù)器斷開連接。

如果在以上過程中的某一步出現(xiàn)錯誤,那么產(chǎn)生錯誤的信息將返回到客戶端,有顯示屏輸出。對于用戶來說,這些過程是由HTTP自己完成的,用戶只要用鼠標(biāo)點擊,等待信息顯示就可以了。

HTTP的基本工作流程如下:

(1)建立TCP連接:客戶端與服務(wù)器建立TCP套接字連接。

(2)發(fā)送HTTP請求:客戶端TCP套接字向服務(wù)器發(fā)送請求報文。

(3)服務(wù)器接受請求并返回HTTP響應(yīng):服務(wù)器解析請求,定位請求資源,并把資源數(shù)據(jù)寫入TCP套接字,由客戶端讀取。

(4)釋放連接TCP連接:若connection 模式為close,則服務(wù)器主動關(guān)閉TCP連接;若connection 模式為keepalive,則該連接會保持一段時間,在該時間內(nèi)可以繼續(xù)接收請求。

客戶端發(fā)送一個HTTP請求到服務(wù)器的請求消息包括以下格式:請求行(request line)、請求頭部(header)、空行和請求數(shù)據(jù)四個部分組成,下圖給出了請求報文的一般格式。

HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),網(wǎng)絡(luò)協(xié)議,http,udp

  • 請求行:包括請求方法如GET、POST等,請求URI:資源的地址和協(xié)議版本。

  • 請求頭部:通知服務(wù)器客戶端的請求信息。鍵值對形式出現(xiàn),每行一對,關(guān)鍵字和值用英文冒號“:”分隔。

  • 空行:分隔請求頭部和請求數(shù)據(jù)的。

  • 請求數(shù)據(jù):GET方法中不使用,POST方法中使用。一般是存儲post的參數(shù)和參數(shù)數(shù)據(jù)。

常用請求頭部字段:

  • Accept:客戶端可接受的信息類型,如text/html,application/xhtml+xml

  • Accept-Charset:客戶端可接受的字符集,如gb2312

  • Accept-Encoding:客戶端可接受的編碼方式,如gzip

  • Accept-Language:客戶端可接受的語言類型,如:zh-CN

  • Authorization:HTTP身份驗證的憑證

  • Content-Length:設(shè)置請求體的字節(jié)長度,get請求可以沒有,post請求必須包含這個

  • Host:設(shè)置服務(wù)器域名和TCP端口號,http協(xié)議,80端口就可以省略

  • Referer:客戶端通過這個頭告訴服務(wù)器,它是從哪個資源來訪問服務(wù)器的,也就是防盜鏈

  • User-Agent:包含發(fā)出請求的客戶端信息,瀏覽器類型/版本等,如:Mozilla/5.0 (Windows NT 10.0; Win64; x64)

  • Cookie:在客戶端記錄信息確定用戶身份,設(shè)置服務(wù)器時使用set-cookie

  • Cache-Control:怎樣處理緩存,例如:Cache-Control: no-cache

  • From:客戶端的的email地址

  • Connection:告訴服務(wù)器這個客戶端想要使用怎樣的連接方式,值為keep-alive和close

HTTP響應(yīng)也由四個部分組成,分別是:狀態(tài)行、消息報頭、空行和響應(yīng)正文。

HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),網(wǎng)絡(luò)協(xié)議,http,udp

示例:
HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),網(wǎng)絡(luò)協(xié)議,http,udp

常用響應(yīng)頭部字段:

  • Content-Encoding:服務(wù)器通過這個頭告訴瀏覽器數(shù)據(jù)的壓縮格式。

  • Content-Length:服務(wù)器通過這個頭告訴瀏覽器回送數(shù)據(jù)的長度。

  • Content-Disposition:告訴瀏覽器以下載方式打開數(shù)據(jù)。

  • Content-Type:服務(wù)器通過這個頭告訴瀏覽器回送數(shù)據(jù)的類型

  • Last-Modified:指定服務(wù)器上保存內(nèi)容的最后修訂時間。

  • Location:重定向的跳轉(zhuǎn)的路徑

  • Refresh :定時刷新/定時跳轉(zhuǎn)

  • server:服務(wù)器信息

  • set-Cookie:cookie信息

響應(yīng)狀態(tài)碼類別:

  • 1XX:指定客戶端進(jìn)行某些動作

  • 2XX:請求處理成功

  • 3XX:重定向

  • 4XX:客戶端請求錯誤

  • 5XX:服務(wù)端錯誤

常用狀態(tài)碼:
200 請求成功,服務(wù)器成功返回內(nèi)容。注意:狀態(tài)碼為200,不代表返回的響應(yīng)數(shù)據(jù)一定是對的(一定是我們想要請求的數(shù)據(jù)),這只代表服務(wù)器正常響應(yīng)了客戶端請求。
301 永久重定向
302 臨時重定向
400 請求語法錯誤或參數(shù)錯誤
403 服務(wù)器拒絕執(zhí)行請求
404 服務(wù)器找不到請求資源
500 服務(wù)器故障無法提供服務(wù)
503 服務(wù)器超負(fù)載或停機維護(hù),一段時間后能提供服務(wù)

HTTP消息結(jié)構(gòu)

相關(guān)問題

HTTP中Get和Post比較

  1. GET和POST本質(zhì)上就是TCP鏈接,本質(zhì)并無差別;
  2. GET產(chǎn)生一個TCP數(shù)據(jù)包;POST產(chǎn)生兩個TCP數(shù)據(jù)包。但并不是所有瀏覽器都會在POST中發(fā)送兩次包,F(xiàn)irefox就只發(fā)送一次。
  3. GET把參數(shù)包含在URL中,POST通過request body傳遞參數(shù)。
  4. get安全性非常低,post安全性較高。 因為參數(shù)直接暴露在URL上,所以不建議使用get請求來傳遞敏感信息。
  5. GET在瀏覽器回退時是無害的,而POST會再次提交請求。
  6. GET請求只能進(jìn)行url編碼,而POST支持多種編碼方式。
  7. GET請求會被瀏覽器主動緩存,而POST不會,除非手動設(shè)置。GET請求參數(shù)會被完整保留在瀏覽器歷史記錄里,而POST中的參數(shù)不會被保留
  8. GET請求在URL中傳送的參數(shù)是有長度限制的,不能大于2KB。而POST沒有。對參數(shù)的數(shù)據(jù)類型,GET只接受ASCII字符,而POST沒有限制。

Cookie和Session

HTTP簡單概述

UDP

UDP協(xié)議端格式:
HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),網(wǎng)絡(luò)協(xié)議,http,udp
以上是為了排版好看,在真實傳輸中為以下樣式:

HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),網(wǎng)絡(luò)協(xié)議,http,udp

  • 源端口
    16位,2個字節(jié);表示發(fā)送方的端口
  • 目的端口號
    16位,2個字節(jié);表示接收方的端口
  • 包長度
    指示了UDP數(shù)據(jù)報的整個長度,共16位,占兩個字節(jié),包括UDP首部和數(shù)據(jù)部分。
    2個字節(jié)能表示的數(shù)據(jù)范圍是0~65535,也就是能夠表示的報文長度是65536字節(jié)(Byte),轉(zhuǎn)換成KB,65536/1024 = 64 KB 這就是一個UDP報文所能表示的最大長度.
  • 校驗和
    用于校驗報文的完整性,該字段稱為校驗和(checksum)。校驗和字段用于驗證UDP數(shù)據(jù)報在傳輸過程中是否發(fā)生了損壞或錯誤。
    數(shù)據(jù)在傳輸?shù)臅r候,本質(zhì)上是0/1bit流,通過光信號或者電信號來表示,如果在傳輸?shù)臅r候收到干擾,就可能會出現(xiàn)比特翻轉(zhuǎn)現(xiàn)象.這個時候就需要校驗和校驗數(shù)據(jù)是否出錯。若校驗和出錯,會直接丟棄。

協(xié)議報頭里面最多就給安排了2個字節(jié)表示端口號,因此最大帶端口號取值區(qū)間換算十進(jìn)制為0-65535,如果你設(shè)置一個特別大的數(shù),它也放不下!

我們能不能把UDP這里的端口空間改成4個字節(jié)?答案:改不了。
原因:

  • 這個代碼是由操作系統(tǒng)內(nèi)核上實現(xiàn)的,你想改?你都拿不到Windows的原碼,你怎么改。
  • 就算你把自己電腦的操作系統(tǒng)內(nèi)核給改了,但是其他主機跟你電腦通信的時候,你也能把別人主機的UDP協(xié)議給改了嗎?肯定是不能,充其量就是把自己的給改了。這樣就會導(dǎo)致對方主機解析你的數(shù)據(jù),或者解析錯誤,導(dǎo)致無法進(jìn)行通信。
  • 也沒有必要去修改這個東西,兩個字節(jié),6萬多個足夠了。

UDP傳輸數(shù)據(jù)大于64k情況:

UDP報文長度是2個字節(jié)表示,范圍是O-65535,進(jìn)一步的講范圍就是0-64k。如果確實需要傳一個大的數(shù)據(jù)。
可以在應(yīng)用層,針對大的數(shù)據(jù)報,進(jìn)行分包(拆成過個部分)。然后,再通過多個UDP數(shù)據(jù)報分別發(fā)送。

但是分別發(fā)送也有很大的問題: 順序是不能保證的! 可能會出現(xiàn)“后發(fā)先制”。

這個時候接收方需要把收到的幾個包重新拼接成完整的數(shù)據(jù)。這種解決方案,雖然能解決問題,但是屬于下策。
原因:太麻煩了!分包和組包的代碼,寫起來非常復(fù)雜,要考慮很多情況(丟包,包的順序錯誤等問題)。

直接上TCP即可。

UDP 協(xié)議首部中有一個 16 位的最大長度。也就是說一個 UDP 能傳輸?shù)臄?shù)據(jù)最大長度是 64K (包含 UDP 首部)。

關(guān)于校驗和 :

HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),網(wǎng)絡(luò)協(xié)議,http,udp

常見基于UDP的應(yīng)用層協(xié)議

  • NFS:網(wǎng)絡(luò)文件系統(tǒng)
  • TFTP:簡單文件傳輸協(xié)議
  • DHCP:動態(tài)主機配置協(xié)議
  • BOOTP:啟動協(xié)議(用于無盤設(shè)備啟動)
  • DNS:域名解析協(xié)議

什么時候應(yīng)該使用UDP?

當(dāng)對網(wǎng)絡(luò)通訊質(zhì)量要求不高的時候,要求網(wǎng)絡(luò)通訊速度能盡量的快,這時就可以使用UDP。

TCP

TCP,即Transmission Control Protocol,傳輸控制協(xié)議。人如其名,要對數(shù)據(jù)的傳輸進(jìn)行一個詳細(xì)的控制。

TCP在傳輸鏈路中屬于傳輸層,TCP報文如下圖所示:

HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),網(wǎng)絡(luò)協(xié)議,http,udp

HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),網(wǎng)絡(luò)協(xié)議,http,udp

  • 源端口號(Source Port)
    16位的源端口字段包含初始化通信的端口號。源端口和IP地址的作用是標(biāo)識報文的返回地址。

  • 目的端口號(Destination Port)
    16位的目的端口字段定義傳輸?shù)哪康?。這個端口指明接收方計算機上的應(yīng)用程序接口。

  • 序列號(Sequence Number)
    該字段用來標(biāo)識TCP源端設(shè)備向目的端設(shè)備發(fā)送的字節(jié)流,它表示在這個報文段中的第幾個數(shù)據(jù)字節(jié)。序列號是一個32位的數(shù)。當(dāng)SYN出現(xiàn),序列碼實際上是初始序列碼(ISN),而第一個數(shù)據(jù)字節(jié)是ISN+1。用來標(biāo)識從TCP源端向TCP目標(biāo)端發(fā)送的數(shù)據(jù)字節(jié)流,它表示在這個報文段中的第一個數(shù)據(jù)字節(jié)。

  • 確認(rèn)號(Acknowledge Number)
    TCP使用32位的確認(rèn)號字段標(biāo)識期望收到的下一個段的第一個字節(jié),并聲明此前的所有數(shù)據(jù)已經(jīng)正確無誤地收到,因此,確認(rèn)號應(yīng)該是上次已成功收到的數(shù)據(jù)字節(jié)序列號加1。收到確認(rèn)號的源計算機會知道特定的段已經(jīng)被收到。確認(rèn)號的字段只在ACK標(biāo)志被設(shè)置時才有效。

  • 首部長度
    長度為4位,用于表示TCP報文首部的長度。用4位(bit)表示,十進(jìn)制值就是[0,15],一個TCP報文前20個字節(jié)是必有的,后40個字節(jié)根據(jù)情況可能有可能沒有。如果TCP報文首部是20個字節(jié),則該位應(yīng)是20/4=5。

  • 保留位(Reserved)
    長度為6位,必須是0,它是為將來定義新用途保留的。

  • 標(biāo)志(Code Bits)
    長度為6位,在TCP報文中不管是握手還是揮手還是傳數(shù)據(jù)等,這6位標(biāo)志都很重要。6位從左到右依次為:

    • URG:緊急標(biāo)志位,如果URG為1,表示這是一個攜有緊急資料的封包。
    • ACK:確認(rèn)標(biāo)志位,說明確認(rèn)序號有效; 取1時表示應(yīng)答字段有效,也即TCP應(yīng)答號將包含在TCP段中,為0則反之。如果ACK為1,表示此封包屬于一個要回應(yīng)的封包。一般都會為1。
    • PSH:推標(biāo)志位,置位時表示接收方應(yīng)立即請求將報文交給應(yīng)用層;如果PSH為1,此封包所攜帶的數(shù)據(jù)會直接上傳給上層應(yīng)用程序而無需經(jīng)過TCP處理。
    • RST:復(fù)位標(biāo)志,用于重建一個已經(jīng)混亂的連接,用來復(fù)位產(chǎn)生錯誤的連接,也會用來拒絕錯誤和非法的數(shù)據(jù)包。如果RST為1,要求重傳。表示要求重新設(shè)定封包再重新傳遞。
    • SYN:同步標(biāo)志,該標(biāo)志僅在三次握手建立TCP連接時有效。如果SYN為1,表示要求雙方進(jìn)行同步溝通。
    • FIN:結(jié)束標(biāo)志,表示發(fā)送端已經(jīng)發(fā)送到數(shù)據(jù)末尾,數(shù)據(jù)傳送完成,發(fā)送FIN標(biāo)志位的TCP段,連接將被斷開。如果FIN為1,表示傳送結(jié)束,然後雙方發(fā)出結(jié)束回應(yīng)進(jìn)而正式終止一個TCP傳送過程。
  • 窗口大小(Window Size)
    長度為16位,TCP流量控制由連接的每一端通過聲明的窗口大小來提供。

  • 檢驗和(Checksum)
    長度為16位,該字段覆蓋整個TCP報文端,是個強制性的字段,是由發(fā)送端計算和存儲,到接收端后,由接收端進(jìn)行驗證。

  • 緊急指針(Urgent Pointer)
    長度為16位,指向數(shù)據(jù)中優(yōu)先部分的最后一個字節(jié),通知接收方緊急數(shù)據(jù)的長度,該字段在URG標(biāo)志置位時有效。

  • 選項(Options)
    長度為0-40B(字節(jié)),必須以4B為單位變化,必要時可以填充0。通常包含:最長報文大?。∕aximumSegment Size,MSS)、窗口擴(kuò)大選項、時間戳選項、選擇性確認(rèn)(Selective ACKnowlegement,SACK)等。

  • 數(shù)據(jù)
    可選報文段數(shù)據(jù)部分。

報文字段解析

標(biāo)志解析

連接管理(三次握手/四次揮手)

連接管理,也是 TCP 保證可靠性的一個機制。

連接管理,說具體點:

  • 兩個設(shè)備之間是如何建立連接的?
  • 兩個設(shè)備之間是如何斷開連接的?

TCP 連接管理,是網(wǎng)絡(luò)部分最高頻的面試題,沒有之一?。?!

三次握手

HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),網(wǎng)絡(luò)協(xié)議,http,udp

  • 第一次握手: 建立連接。客戶端發(fā)送連接請求報文段,將SYN位置為1,Sequence
    Number為x;然后,客戶端進(jìn)入SYN_SEND狀態(tài),等待服務(wù)器的確認(rèn);

  • 第二次握手: 服務(wù)器收到SYN報文段。服務(wù)器收到客戶端的SYN報文段,需要對這個SYN報文段進(jìn)行確認(rèn),設(shè)置Acknowledgment Number為x+1(Sequence Number+1);同時,自己還要發(fā)送SYN請求信息,將SYN位置為1,Sequence Number為y;服務(wù)器端將上述所有信息放到一個報文段(即SYN+ACK報文段)中,一并發(fā)送給客戶端,此時服務(wù)器進(jìn)入SYN_RECV狀態(tài);

  • 第三次握手: 客戶端收到服務(wù)器的SYN+ACK報文段。然后將Acknowledgment Number設(shè)置為y+1,向服務(wù)器發(fā)送ACK報文段,這個報文段發(fā)送完畢以后,客戶端和服務(wù)器端都進(jìn)入ESTABLISHED狀態(tài),完成TCP三次握手。

HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),網(wǎng)絡(luò)協(xié)議,http,udp

當(dāng)SYN這一位為1,表示當(dāng)前報文就是一個“同步報文段”。意思就是:主機A與主機B之間要建立連接。
當(dāng)ACK"這一位為1的時候,它就是一個“確認(rèn)報文段”。表示它是起到一個應(yīng)答的效果,用來確認(rèn)消息已經(jīng)是送到了的。
這樣的一個雙向奔赴就構(gòu)成一個建立連接的過程。
當(dāng)雙方都建立連接之后,客戶端與服務(wù)器建立了連接,服務(wù)器和客戶端建立了連接。

首先,客戶端先給服務(wù)器發(fā)起了一個SYN同步請求。

HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),網(wǎng)絡(luò)協(xié)議,http,udp

HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),網(wǎng)絡(luò)協(xié)議,http,udp

此時我們就發(fā)現(xiàn):不是說三次握手嗎?這里怎么又四次了?
其實中間的兩次,是一定合二為一的,再進(jìn)行發(fā)送。
每次要傳輸?shù)臄?shù)據(jù),都要經(jīng)過一系列的封裝和分用,才能完成傳輸。
如果分開發(fā),ACK一條,SYN一條。這兩條都是需要網(wǎng)絡(luò)層、數(shù)據(jù)鏈路層的封裝的,物理層再去轉(zhuǎn)換,最后再發(fā)送給對方。對方接收到信息,再進(jìn)行一頓分用解析操作。
道理很簡單,你一次封裝發(fā)送,就能解決問題,分二次發(fā)送,這不是浪費時間嘛!

因此 ACK和SYN可以合成一條發(fā)送:把下面的6個標(biāo)志位中ACK和SYN分別設(shè)為1
HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),網(wǎng)絡(luò)協(xié)議,http,udp
最終變成:
HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),網(wǎng)絡(luò)協(xié)議,http,udp

為什么要三次握手?

為了防止已失效的連接請求報文段突然又傳送到了服務(wù)端,因而產(chǎn)生錯誤。

  • 相當(dāng)于“投石問路”,也就是檢查一下當(dāng)前這個網(wǎng)絡(luò)的情況是否滿足可靠傳輸?shù)幕緱l件。如果你網(wǎng)絡(luò)本身就很差,強行進(jìn)行TCP傳輸,也會涉及到大量的丟包。這個時候,我們就直接不去進(jìn)行可靠傳輸,讓TCP就不工作了,省點力氣。
  • 讓雙方能夠協(xié)商一些必要的信息。

總結(jié):為了保證雙方的發(fā)送和接收都沒有問題。

四次揮手

HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),網(wǎng)絡(luò)協(xié)議,http,udp
簡化 :
HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),網(wǎng)絡(luò)協(xié)議,http,udp

TCP協(xié)議是一種面向連接的、可靠的、基于字節(jié)流的運輸層通信協(xié)議。TCP是全雙工模式,這就意味著,當(dāng)主機1發(fā)出FIN報文段時,只是表示主機1已經(jīng)沒有數(shù)據(jù)要發(fā)送了,主機1告訴主機2,它的數(shù)據(jù)已經(jīng)全部發(fā)送完畢了;但是,這個時候主機1還是可以接受來自主機2的數(shù)據(jù);當(dāng)主機2返回ACK報文段時,表示它已經(jīng)知道主機1沒有數(shù)據(jù)發(fā)送了,但是主機2還是可以發(fā)送數(shù)據(jù)到主機1的;當(dāng)主機2也發(fā)送了FIN報文段時,這個時候就表示主機2也沒有數(shù)據(jù)要發(fā)送了,就會告訴主機1,我也沒有數(shù)據(jù)要發(fā)送了,之后彼此就會愉快的中斷這次TCP連接。

  • 第一次揮手: 主機1(可以是客戶端,也可以是服務(wù)器端),設(shè)置Sequence Number,向主機2發(fā)送一個FIN報文段;此時,主機1進(jìn)入FIN_WAIT_1狀態(tài);這表示主機1沒有數(shù)據(jù)要發(fā)送給主機2了;

  • 第二次揮手: 主機2收到了主機1發(fā)送的FIN報文段,向主機1回一個ACK報文段,Acknowledgment Number為Sequence Number加1;主機1進(jìn)入FIN_WAIT_2狀態(tài);主機2告訴主機1,我“同意”你的關(guān)閉請求;

  • 第三次揮手: 主機2向主機1發(fā)送FIN報文段,請求關(guān)閉連接,同時主機2進(jìn)入LAST_ACK狀態(tài);

  • 第四次揮手: 主機1收到主機2發(fā)送的FIN報文段,向主機2發(fā)送ACK報文段,然后主機1進(jìn)入TIME_WAIT狀態(tài);主機2收到主機1的ACK報文段以后,就關(guān)閉連接;此時,主機1等待2MSL后依然沒有收到回復(fù),則證明Server端已正常關(guān)閉,那好,主機1也可以關(guān)閉連接了。

HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),網(wǎng)絡(luò)協(xié)議,http,udp
6個標(biāo)記位中的 FIN為1,表示這是一個“結(jié)束報文段”。

三次握手和四次揮手最大的區(qū)別就是:

  • 三次握手,一定是客戶端主動發(fā)起的(主動發(fā)起的一方才叫客戶端)
    四次揮手,可能是客戶端主動發(fā)起,也可能是服務(wù)器主動發(fā)起。【男女都能提出分手】

  • 三次握手,中間的兩次可以合并。
    四次揮手,中間的兩次,有時候是合并不了的。(有時候是能合并的)

如果中間的兩次能合并,那就是三次揮手。如果合并不了,那就是4次揮手。

不能合并的原因在于B發(fā)送ACK和B發(fā)送FIN的時機是不同的,而像三次握手的過程,中間發(fā)送SYN和ACK是同一時機。

  • 三次握手中,B 給A發(fā)送ACK和SYN都是操作系統(tǒng)內(nèi)核處理的。
  • 四次揮手中,B給A發(fā)送的 ACK,是操作系統(tǒng)內(nèi)核處理的;

服務(wù)端B給客戶端A發(fā)送的FIN,是用戶代碼負(fù)責(zé)的。
換個說法:B的代碼中,調(diào)用了socket.close方法,才會觸發(fā)FIN。
如果這兩個都是操作系統(tǒng)內(nèi)核負(fù)責(zé)處理的,內(nèi)核就可以安排他們兩個合并一下。但是,這里現(xiàn)在一個ACK是內(nèi)核負(fù)責(zé),一個FIN是用戶代碼(應(yīng)用層)負(fù)責(zé)的。

  • 內(nèi)核負(fù)責(zé):收到FIN,立即就由內(nèi)核進(jìn)行反饋(ACK)
  • 用戶代碼負(fù)責(zé):執(zhí)行到用戶代碼中的close,才會觸發(fā)FIN。

什么時候觸發(fā)FIN,取決于用戶代碼是怎么寫的。
如果代碼的邏輯比較短,那么很快就能執(zhí)行到close;也有可能,在執(zhí)行close之前,要進(jìn)行很多其他的工作,可能就需要過很久才能調(diào)用close。
最壞情況下,在執(zhí)行 close之前,代碼出現(xiàn)bug,導(dǎo)致無法執(zhí)行到close方法,那么FIN就一直都觸發(fā)不了。

所以,一個是用戶代碼觸發(fā)的實際,一個是內(nèi)核時機,這是兩個不同的時機。
如果兩個操作之間時差比較大,那就沒有辦法進(jìn)行合并。
如果兩個操作之間時差比較小,那就可能進(jìn)行合并。

合并操作,又稱延時應(yīng)答捎帶應(yīng)答??傊@個4次揮手,可能是4次揮完,也可能是3次會完。關(guān)鍵看中間的ACK和FIN的執(zhí)行時間的間隔有多長。但是,用戶代碼這個東西,有很多的不確定性,所以,我們一般認(rèn)為是4次揮手。

4次揮手復(fù)雜的邏輯

TCP可靠傳輸(確認(rèn)答應(yīng))

如果發(fā)送消息之后,能夠知道對方 收到/沒收到 數(shù)據(jù),就是可靠的。
反之,發(fā)送消息之后,不知道對方 收到/沒收到 數(shù)據(jù),就是不可靠的。

TCP就是為了解決這個可靠性問題。解決方案:接收方 收到消息之后,就給發(fā)送方返回一個應(yīng)答報文(ACK - acknowledge),表示自己已經(jīng)收到了。

TCP每發(fā)送報文時候,針對每一個字節(jié)都進(jìn)行編號,發(fā)送的時候?qū)⑿蛱栐O(shè)置為當(dāng)前字節(jié)的開始編號及結(jié)束編號:HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),網(wǎng)絡(luò)協(xié)議,http,udp
發(fā)送時設(shè)置序號:
HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),網(wǎng)絡(luò)協(xié)議,http,udp

如圖所示兩次發(fā)送過程:

  • 主機A 給主機B發(fā)送了一千個字節(jié)的數(shù)據(jù),序號就是1-1000。
    主機B給主機A返回的應(yīng)答報文(ACK)就會帶有一個確認(rèn)序號,叫做1001;表示小于1001的數(shù)據(jù)都已經(jīng)被主機B收到了,接下來,主機A應(yīng)該從1001這個序號開始往后進(jìn)行傳遞。

  • 主機A給主機B發(fā)送了一千個字節(jié)的數(shù)據(jù),序號就是1001 - 2000。
    主機B給主機A返回的應(yīng)答報文(ACK)就會帶有一個確認(rèn)序號,叫做2001;表示小于2001的數(shù)據(jù)都已經(jīng)被主機B收到了,接下來,主機A應(yīng)該從2001這個序號開始往后進(jìn)行傳遞。

這里發(fā)送的數(shù)據(jù)是1 - 1000;意思是TCP報頭中的序號是1,報文長度是1000通過這個信息,來明確范圍。

超時重傳

相當(dāng)于對確認(rèn)應(yīng)答進(jìn)行了補充 。確認(rèn)應(yīng)答是在網(wǎng)絡(luò)一切正常的時候,通過 ACK 通知發(fā)送方,我收到了。如果出現(xiàn)了丟包的情況,超時重傳機制就要起到效果了。

作為發(fā)送方我們是無法確認(rèn)接收ACK失敗的原因是哪一種。反過來說,我們能確認(rèn)數(shù)據(jù)是否能到達(dá),全依仗的是ACK。在我們的眼中有以下幾種可能:

  • 服務(wù)器沒有收到我們的消息
  • 服務(wù)器收到了,但是沒有看到
  • 服務(wù)器收到了,但是沒回復(fù)
  • 服務(wù)器收到了,并且也做出了回復(fù),但是我們沒有收到。

這時候,我們就直接往壞的想:就認(rèn)為對方壓根就沒有收到,于是我們流重新再發(fā)一次。
但是,也不是立刻就進(jìn)行重發(fā)。我們得等一會,給點反應(yīng)時間,畢竟網(wǎng)絡(luò)傳輸數(shù)據(jù),需要時間對方處理信息,并且按下發(fā)送鍵,也是需要時間的。
如果我等了10分鐘,還沒有收到ACK,就重發(fā)一次。這個就叫作超時重傳:超出了等待時間,就進(jìn)行重傳。

超時重傳的問題:
在第一種情況下,因為服務(wù)器沒有收到過信息,所以再次重發(fā)也不會有問題。
但第二種情況下,就有問題了:因為我們作為發(fā)送方式無法判斷就收ACK失敗的原因,所以,我們還會重發(fā)一次。這不就重復(fù)發(fā)送消息了嘛!

換句話來說:如果是ACK丟了,此時就會觸發(fā)超時重傳,就會導(dǎo)致接收方收到了重復(fù)的消息。其實這是一個非常嚴(yán)重的問題,如果換成轉(zhuǎn)賬操作,那這種操作就很危險了。

所以TCP內(nèi)部就會一個去重操作:接收方收到的數(shù)據(jù),會先放到操作系統(tǒng)內(nèi)核的“接收緩沖區(qū)”中。

接收緩沖區(qū):可以視為一個內(nèi)存空間,并且也可以視為是一個阻塞隊列。
收到新的數(shù)據(jù),TCP就會根據(jù)序號,來檢查這個數(shù)據(jù)是不是在接收緩沖區(qū)中已經(jīng)存在了。如果不存在,就放進(jìn)去。
如果存在,就直接丟棄。保證應(yīng)用程序調(diào)用socket API拿到的這個數(shù)據(jù)一定是不重復(fù)的!

應(yīng)用程序是感知不到超時重傳的過程的,這是TCP內(nèi)部,幫我們解決了一個很大的問題!

HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),網(wǎng)絡(luò)協(xié)議,http,udp
HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),網(wǎng)絡(luò)協(xié)議,http,udp

基于上述的兩個機制,TCP 的可靠性,就得到了有效的保障。
一個是針對 順利的情況下,它是怎么處理的,這就是確認(rèn)應(yīng)答。
一個是 針對 通信丟包了,是怎么處理的,那就是超時重傳
這兩者相結(jié)合,其實我們就可以解決很多很多的問題。
但是呢!TCP 這樣的協(xié)議,它是不滿足于上述這兩點的。它希望它能做得更好,更加極致。

滑動窗口

在沒有滑動窗口機制下,沒發(fā)送一個數(shù)據(jù)包,就需要等對方機器確認(rèn)是否收到,再繼續(xù)發(fā)送下一個包:

HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),網(wǎng)絡(luò)協(xié)議,http,udp

主機A給主機B發(fā)送數(shù)據(jù)之后((1-1000),B要給A返回一個ACK (1001) .
A拿到 ACK(1001)之后,A才能說,從哪個位置(1001〉開始繼續(xù)傳輸數(shù)據(jù)(1001 - 2000)。

因為畢竟A要拿到ACK才能知道前面發(fā)送的數(shù)據(jù)(1-1000),對方是收到了的。
如果等待一段時間后,A并沒有拿到B的 ACK。此時,就會觸發(fā)超時重傳,A重新發(fā)送數(shù)據(jù)(1-1001)

上述的操作:每次都發(fā)一條數(shù)據(jù),然后等到收到ACK之后,才能發(fā)送下一條數(shù)據(jù)。這樣的操作是非常低效的。此時,大量的時間都花在等待ACK上了。

因此引入“滑動窗口的機制”。滑動窗口:本質(zhì)就是在“批量的發(fā)送數(shù)據(jù)”:
批量的發(fā)送數(shù)據(jù):一次發(fā)一波數(shù)據(jù)(數(shù)條數(shù)據(jù)),然后一起等一波ACK。所以,這個時候就能近一步的縮小等待時間,從而提高傳輸?shù)男省?/p>

HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),網(wǎng)絡(luò)協(xié)議,http,udp

上例一次發(fā)送了四組數(shù)據(jù):

1 ~ 1000
1001 ~ 2000
2001 ~ 3000
3001 ~ 4000

在發(fā)送這4組數(shù)據(jù)的過程中,不進(jìn)行等待。發(fā)完這4組數(shù)據(jù)之后,再統(tǒng)一等待。這就意味一份等待時間,我們等待了多條ACK??梢赃@么去理解:把等待多條ACK的時間壓縮成一份了。
我們提高傳輸效率的關(guān)鍵:縮短等待時間。但是我們不能完全不等ACK,不等就肯定不是可靠傳輸了。就相當(dāng)于拋棄了可靠傳輸,TCP也就失去了存在的意義了。

如果—次批量發(fā)送數(shù)據(jù)為N,統(tǒng)一等待—波。此時,這里的N就被稱為“窗口大小”。
窗口大小:我們把一次發(fā)送多少數(shù)據(jù),并且中間不用等。我們將這個數(shù)據(jù)的大小,稱之為“窗口大小”。所以“窗口”,這個詞也就出來了。

滑動的理解:并不用把N組數(shù)據(jù)的ACK都等到了,才繼續(xù)往下執(zhí)行/發(fā)送數(shù)據(jù)。而是收到一個ACK,就繼續(xù)往下發(fā)送一組數(shù)據(jù)。

例如上圖:1-1000字節(jié)的數(shù)據(jù)先到達(dá)主機B。主機B的操作系統(tǒng)內(nèi)核,就立即反饋一條ACK(1001),表示數(shù)據(jù)(1001)收到了。也就是說:這個1001 (ACK)一到A,主機A立馬就可以繼續(xù)發(fā)送4001-5000 。

HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),網(wǎng)絡(luò)協(xié)議,http,udp

當(dāng)前這個“窗口的大小”越大,就可以認(rèn)為是傳輸速度就越快。
“窗口”越大,意味著在同一份等待時間里,發(fā)送的數(shù)據(jù)就越多.返回的ACK也越多。換個角度,每個ACK之間的時間間隔就越小,等到一個ACK的時間,也就越短。所以,窗口的大小越大,它執(zhí)行效率就越高。

關(guān)于丟包:

丟包分成兩種情況:

1、ACK丟了
例如在發(fā)送4001的數(shù)據(jù)之前,發(fā)送收到了一個2001,1001并沒有收到。但是,其實仔細(xì)一想,不要緊。
因為 2001表示的意思就是:2001之前的數(shù)據(jù)都已經(jīng)確認(rèn)收到了。1001能否被收到,就無關(guān)緊要了。
由于ACK確認(rèn)序號的含義,就保證了后一條ACK就能涵蓋前一條。確認(rèn)序號的含義:表示當(dāng)前序號之前的數(shù)據(jù)都接收到了
2001:表示1-2000的數(shù)據(jù)已經(jīng)被接收到了。
1001:表示1-1000的數(shù)據(jù)已經(jīng)被接收到了。1-2000已經(jīng)涵蓋了1-1000的數(shù)據(jù)。既然如此,1001這條ACK丟就丟了,無所謂。發(fā)送方只要收到5001,意味著1-5000的數(shù)據(jù)就就接收到了。那么,即使3001, 4001這兩個ACK丟包也毫無影響。

假設(shè):先要等待4組ACK:1001,2001,3001, 4001
如果直接收到了4001,前面就都不用等了。直接再發(fā)4組數(shù)據(jù)。也就是說:滑動窗口,滑動的跨度是不是固定的,而是動態(tài)的。
最終結(jié)論:只要不是最后一個ACK丟包,就不用管。
如果最后一個ACK丟包了,就會回到原始的一個機制,超時重傳。將最后一個ACK補齊。

2、數(shù)據(jù)丟了
首先,主機B收到1-1000,反饋一個ACK(1001)下面,主機A發(fā)送1001 -2000,但是丟包了。
接著主機A發(fā)送2001-3000,主機B仍然返回一個1001。包括后面的3001 -4000,4001-5000,5001-6000的數(shù)據(jù)到了,也還是返回1001。
由于1001-2000這個數(shù)據(jù)包丟了,所以主機B就向A反復(fù)索要1001-2000這個數(shù)據(jù)。即使A已經(jīng)給了B后續(xù)的數(shù)據(jù),B仍然是向A索要1001-2000的數(shù)據(jù)。
當(dāng)A被B索要若干次之后,A就明白了【這個數(shù)據(jù)報,它給弄丟了】,于是就觸發(fā)重傳。而且,下一個ACK立馬就變成7001 了。因為3001 - 7000的數(shù)據(jù),都已經(jīng)接收到了,所以下一個直接7001就可以了。

HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),網(wǎng)絡(luò)協(xié)議,http,udp

其實這個重傳的過程,還是比較高效的。誰丟了就重傳誰,而不是說把丟了的數(shù)據(jù),從這往后全都重傳一遍。因此,整體的過程,還是比較高效的,我們將其稱為快重傳。

流量控制

流量控制,是滑動窗口的延伸,目的是為了保證可靠性。在滑動窗口中,窗口越大(一次傳輸?shù)臄?shù)據(jù)量),傳輸速率也就越高。
?
那么,有些朋友就會這么去想:我把窗口弄得越大越好,這樣的我們數(shù)據(jù)傳輸量就大幅度提升了。答案是不行:
把窗口弄大,不光要考慮發(fā)送方,還得考慮接收方。如果發(fā)送方發(fā)送的速度非常快,接收方完全就處理不過來,接收方就會把新接收到的包給丟了。那么,發(fā)送方是不是還得重傳,這就不就在浪費時間和資源嘛!

接收方B每次從A接收到的新數(shù)據(jù),都會先存入到一個接收緩沖區(qū)中。
不光是A在往B的接收緩沖區(qū)填充數(shù)據(jù),還有B的應(yīng)用程序在接收緩沖區(qū)中拿數(shù)據(jù),所以B的應(yīng)用程序,在調(diào)用read方法的時候,就是在從接收緩沖區(qū)中來取數(shù)據(jù)。

比如: read讀取到一個字節(jié)的數(shù)據(jù)后,接收緩沖區(qū)中就少一個字節(jié)的數(shù)據(jù)。不管read 一次讀取多少個字節(jié),每read一次,就會取走接收緩沖區(qū)的一部分?jǐn)?shù)據(jù)。

我們可以把這個接收緩沖區(qū)理解成是一個阻塞隊列,這樣的數(shù)據(jù)傳輸過程,就可以理解成生產(chǎn)者消費者模型A就是生產(chǎn)者,B的應(yīng)用程序就是 消費者。接收緩沖區(qū):交易場所/阻塞隊列。

我們這里的接收緩沖區(qū)肯定是有一個總大小,它并不是無限大的。隨著A發(fā)送數(shù)據(jù),接收緩沖區(qū)里就會逐漸放入一些數(shù)據(jù)。因此,接收緩沖區(qū)的剩余空間就會逐漸減小。

  • 如果剩余空間比較大,就認(rèn)為B的處理能力是比較強的,就讓A發(fā)的快點。
  • 如果剩余空間比較小,就認(rèn)為B的處理能力是比較弱的,就讓A發(fā)的慢點。

所以,我們就使用這個剩余空間的大小,來去制約A 的發(fā)送速度。通過這樣的方式,就可以讓A 和B之間,進(jìn)行一個更好的協(xié)調(diào)和適配。站在A的角度來說:

  • 如果B這邊處理的比較快,接收緩沖區(qū)里面的剩余空間就比較大,就可以讓A發(fā)得快點。B也是能夠處理的過來。
  • 如果B這邊處理的比較慢,接收緩沖區(qū)里面的剩余空間就比較小,就可以讓A發(fā)得慢點。讓B能夠處理的過來。

而B怎么通知A自己的處理能力有多少呢?
通過ACK報文來告知。我們不是一給B發(fā)送數(shù)據(jù),B就會返回一個ACK嘛。
那么,返回的 ACK里,就會帶有一個接收緩沖區(qū)的剩余空間大小的信息。這個信息就存儲在TCP報頭里/TCP協(xié)議段格式。

HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),網(wǎng)絡(luò)協(xié)議,http,udp
通過這個16位窗口大小,來衡量當(dāng)前接收方剩余空間的大小。發(fā)送方收到這個數(shù)據(jù)之后,就會靈活的調(diào)整發(fā)送速度(調(diào)整窗口大小)

HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),網(wǎng)絡(luò)協(xié)議,http,udp

當(dāng)A一共給B發(fā)送了4k字節(jié)數(shù)據(jù)的時候,接收緩沖區(qū)還剩0字節(jié)的空間。當(dāng)窗口大小為0的時,是否意味著A就不再發(fā)送數(shù)據(jù)了呢?
是的!A 確實是不發(fā)送了,但又不是完全不發(fā)送。
A需要定期發(fā)送一個探測報文,探測報文不傳輸實際的數(shù)據(jù),它只是為了觸發(fā)ACK。通過ACK來獲取當(dāng)前的窗口大小是多少。后面等到B處理完一定數(shù)據(jù)后,接收緩沖區(qū)還剩余2k字節(jié)。給A發(fā)送一個窗口更新通知(ACK),然后A得知后,就又開始傳輸數(shù)據(jù)了。

這就好比蓄水池滿了,就不應(yīng)該繼續(xù)注水了。但是放水還一直在執(zhí)行。(滿只是一種暫時的狀態(tài),隨著放水持續(xù)的工作,水位會逐漸降低)期間注水人員,會不斷觀察機械探測,返回的水位數(shù)據(jù)。等到水位降低到一定的程度,就又要開始進(jìn)行放水了。

擁塞控制

擁塞控制,也是滑動窗口的延伸,也是用來限制 滑動窗口 發(fā)送的速率。衡量的是 發(fā)送方到接收方,這整個鏈路之間,擁堵情況(處理能力),根據(jù)這個情況,我們來去決定發(fā)送的速率是多少。

首先,要明白A和B之間,不是一根網(wǎng)線直連的,中間存在多個轉(zhuǎn)發(fā)設(shè)備。(路由器/交換機/其他設(shè)備)

A能夠發(fā)多快,不光取決于B的處理能力,也取決于中間鏈路的處理能力。只要這中間任意一環(huán),它的處理速度變慢了,那么整體傳輸?shù)脑倏煲矝]用。即使B的處理速度再快,中間某一環(huán)節(jié)處理的很慢,那么A發(fā)的再快也沒用。解決這個問題的方法就是擁塞控制。

擁塞控制,會根據(jù)中間這些設(shè)備的性能(是否能流暢的傳輸)來決定A的發(fā)送速率。但是,有個問題:A和B之間的中間節(jié)點/中間設(shè)備有多少個?這是不能確定的。所以,很難對這些設(shè)備一個個去衡量。

流量控制是專門針對B處理能力的一種機制,對于B來說,很好觀察。直接查看接收緩沖區(qū)的剩余空間大小就知道了。
但是現(xiàn)在的情況就不一樣了,中間有很多的設(shè)備,中間任意的設(shè)備處理能力弱,都會導(dǎo)致整體的處理效率降低。這個時候,我們就得想辦法來衡量中間設(shè)備,但是中間設(shè)備又多又雜,這要怎么去處理呢?

擁塞控制的處理方案,就是通過“實驗”的方式,逐漸調(diào)整發(fā)送速度。找到一個比較合適的值/范圍,這就是我們實現(xiàn)擁塞控制的關(guān)鍵。由于中間的設(shè)備太多太雜,于是干脆將其視為一個整體。

A開始的時候,以一個比較小的窗口來發(fā)送數(shù)據(jù),如果數(shù)據(jù)很流暢的就到達(dá)了B。這個時候,開始逐漸加大窗口的大小。
如果加大到一定的程度后,出現(xiàn)了丟包?!緛G包就意味著通信鏈路出現(xiàn)了擁堵】這個時候,再減小窗口的的大小。
通過反復(fù)的增大/減小窗口大小的操作,來摸索出一個臨界點(值/范圍)。擁塞窗口就在這個范圍中不斷的變化,達(dá)到“動態(tài)平衡”。

HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),網(wǎng)絡(luò)協(xié)議,http,udp

指數(shù)規(guī)律增長:

現(xiàn)在我們有一個很矛盾的問題:既希望它的執(zhí)行速度快,又希望不丟包。什么時候可以達(dá)到這一點?
窗口的大小無限接近丟包的極限,但是又沒有跨過那道坎。所以沒有真的丟包。這樣形式,是我們最希望的。
就像前面說的:因為初始窗口太小,而我們實際上可能觸發(fā)丟包的值是很大的。利用指數(shù)成長,就能快速摸到即將丟包的界限,更快的接近合適的值。

擁塞控制在最開始的時候,取的初始窗口大小,非常小。
縱軸是1個段位(一個點位具體是1字節(jié),10字節(jié)…這個是不確定的,具體看操作系統(tǒng)的代碼是怎么實現(xiàn)的)如果不丟包,下一輪變成2個單位,還不丟,下一輪4個單位,依次類推,只要不丟包,就成指數(shù)的增長。為什么一開始要指數(shù)增長呢?
這是因為我們給初始窗口太小,而我們實際上可能觸發(fā)丟包的值是很大的。因此指數(shù)成長,就能幫助我們快速摸到即將丟包的界限。

線性增長

但是呢!又不能讓它特別快速的增長,突破那個極限。等到指數(shù)增長到一定的程度時,就會進(jìn)入線性增長。
使用線性增長的目的:主要是因為我們?nèi)绻磳⒔咏鼇G包的極限,你再來一個指數(shù)翻倍增長。
這一下,可能就直接上頭了,挺不住了。

這好比一個運動負(fù)重15kg (30斤),他還能完全適應(yīng)。但是,你一翻倍30kg (60斤),他直接就趴了。因此,應(yīng)該是一點一點的增加,16,17,18… …這樣的增加負(fù)重。這樣運動員才能更好的適應(yīng),即使真的超重了,也不會立即就趴了,還能掙扎一下.這就是一個線性增長的過程。

乘法減小

但是線性增長也是增長啊,勢必會達(dá)到一個擁堵的極限,這個時候就會產(chǎn)生丟包。一旦發(fā)生了丟包,就讓擁塞窗口立即變小?;貧w到初始窗口的大?。ㄗ钚〉哪莻€)繼續(xù)重復(fù)剛才的操作(指數(shù)和線性增長)。

之所以沒有一點一點的減少,而是直接回歸初始大小是因為網(wǎng)絡(luò)的情況是復(fù)雜,且又不穩(wěn)定的。比如:上一次你傳輸一個20k數(shù)據(jù)都沒有,下一次再傳輸20k就可能出現(xiàn)問題。

故:如果出現(xiàn)丟包,很可能你光把速度將下來一點,是不能解決問題的。
因為發(fā)生丟包的原因,都是網(wǎng)絡(luò)上突發(fā)緊急情況,導(dǎo)致網(wǎng)絡(luò)帶寬一下降低很多,這時候你光將下一點沒用!
如果要降低的太慢了,會導(dǎo)致出現(xiàn)持續(xù)性的丟包,對網(wǎng)絡(luò)通信質(zhì)量帶來了很大的影響。一下把窗口變得很小,就是希望這次的傳輸,一定能成功。
如果下一次再失敗,那影響就比較大了,因此每一次丟包都把窗口拉到最小。這樣的話,我們就希望能提升這個最小窗口的傳輸成功率。如果成功了,我們子再來執(zhí)行上述操作(指數(shù)+線性增長),重新去摸索那個界限。

**慢啟動閾值(SSTHRESH) **

慢啟動閾值是擁塞控制中用來限制慢啟動階段發(fā)送窗口大小的門限值,它是慢啟動階段與擁塞避免階段的分界點。
換個說法慢啟動閾值ssthresh,決定了什么時候從指數(shù)增長 -> 線性增長。
這個閾值也不是一直不變的:每次出現(xiàn)丟包,閾值就更新為當(dāng)前出現(xiàn)丟包的窗口大小的一半。意思就是從這個位置,你再來一個指數(shù)翻倍,就會直接丟包了。也就意味著后續(xù)嘗試(指數(shù)增長)操作的時候,達(dá)到這一半,就不會再嘗試翻倍了。所以,這個時候我們用這個新的閾值來去衡量新的線性增長的過程。


問題來了:擁塞窗口和流量窗口都是來制約滑動窗口的大小的。那么,到底聽誰的呢?以誰為主呢?

最終滑動窗口的大小== Math.min(擁塞窗口,流量控制窗口),取兩者的最小值,為主要限制。
其實也很好理解,誰的處理能力低,就遷就誰。不能說它處理能力低,你就不管它的死活,強行帶若它跑吧!

延時應(yīng)答

延時應(yīng)答 相當(dāng)于是 流量控制的延伸。

流量控制 相當(dāng)于是 踩了一下剎車,使發(fā)送方,發(fā)的不要太快。
延時應(yīng)答,就想在這個基礎(chǔ)上,能夠盡量的再讓窗口更大一些。
因為服務(wù)器一直在處理請求,所以服務(wù)器的容積一直在變化中。

具體就是在每次數(shù)據(jù)傳輸?shù)臅r候,不立即返回當(dāng)前服務(wù)器的可處理請求狀態(tài),而是延遲一會兒再返回。在這個延遲時間里面,服務(wù)器會取得更大的容積。這個操作,其實就是在有限的情況下,又盡可能的提高了一點傳輸速度。

延時應(yīng)答,具體延時多少呢?

  1. 數(shù)量限制:每隔N個包就應(yīng)答一次;
  2. 時間限制:超過最大延遲時間就應(yīng)答一次

捎帶應(yīng)答

客戶端和服務(wù)器是通過網(wǎng)絡(luò),進(jìn)行通信??蛻舳撕头?wù)器之間的通信,有以下幾種模型:

  • 一問一答:客戶端每發(fā)送一個請求,服務(wù)器就返回一個對應(yīng)的響應(yīng)。
  • 多問一答:上傳文件,可能會出現(xiàn)的情況
  • 一問多答:下載文件,可能會出現(xiàn)的情況
  • 多問多答:直播,串流。

平時最常用的一個模型:一問一答,比如用瀏覽器上網(wǎng),打開網(wǎng)頁,主要就是這樣的模型。這也是我們在 web開發(fā)中最常使用的一個模型,一個請求對應(yīng)著一個響應(yīng)??蛻舳伺c服務(wù)器之間的交互,也是一問一答的模型。針對這種一問一答,我們的捎帶應(yīng)答就非常的有用,

假設(shè):A給B發(fā)送一個 [ hello,how are you? ]
正常情況下,B收到A的請求之后,肯定是會返回一個ACK的,然后,緊接著B又要回復(fù)一個響應(yīng) [ l 'm fine,thanks。 and you? ’ ] ,A在收到B的響應(yīng)之后,也會返回一個ACK

HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),網(wǎng)絡(luò)協(xié)議,http,udp

這個時候,我們需要明確一點:發(fā)送ACK的時機,是操作系統(tǒng)內(nèi)核響應(yīng)的(立即執(zhí)行)。而B做出的響應(yīng),是應(yīng)用程序返回的。【執(zhí)行到相關(guān)的代碼,才去發(fā)送的】
也就是說:這個B返回的 ACK和響應(yīng),兩者觸發(fā)的時間是不同的(不能進(jìn)行合并),這個延時應(yīng)答的作用就出來了,讓B的 ACK不是馬上返回,而是讓它稍等一會。稍等一會,就可能和響應(yīng)的時間無限接近,甚至是重合。

HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),網(wǎng)絡(luò)協(xié)議,http,udp
既然響應(yīng)和ACK都重合/無限接近了,就可能會把ACK和響應(yīng)進(jìn)行合并。如果進(jìn)行合并了,原本需要傳輸2次數(shù)據(jù),現(xiàn)在只需要傳輸一次,效率自然就提升了。

捎帶應(yīng)答:就是讓兩個發(fā)送時機無限接近/重復(fù)的數(shù)據(jù),進(jìn)行合并。這就是捎帶應(yīng)答的效果:降低消耗,提升效率。

粘包問題

TCP粘包中的“粘”指的是:應(yīng)用層數(shù)據(jù)包/報在TCP 接收緩沖區(qū)中,若干個應(yīng)用層數(shù)據(jù)包/報是混在一起的,
粘包問題:分不出來這些數(shù)據(jù)包都是來自哪個程序的

粘包問題

其他

基于UDP 如何實現(xiàn)可靠傳輸?(看起來是在考UDP,其實是在考TCP)

答案:就是“抄作業(yè)”?。。?!
本質(zhì)上就是在應(yīng)用層基于 UDP 復(fù)刻 TCP的 機制。
保證可靠性 最重要的機制:確認(rèn)應(yīng)答 和 超時重傳,你可以實現(xiàn)一下。實現(xiàn)的同時,要確保這里面 引入 序號 和 確認(rèn)序號。再進(jìn)一步確??煽啃裕阂脒B接管理(三次握手,四次揮手)

反正就是將上面的十個機制,都實現(xiàn)一下。用代碼去實現(xiàn),也就是在應(yīng)用層上實現(xiàn)。?這樣的 UDP 與 TCP的區(qū)別就在于:

  • TCP 這十個機制都是操作系統(tǒng)內(nèi)核代碼實現(xiàn)好了的。
  • UDP 是我們手動敲出來的 十個機制。

UDP 和TCP 的區(qū)別圖示
HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),網(wǎng)絡(luò)協(xié)議,http,udp

HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),網(wǎng)絡(luò)協(xié)議,http,udp

  • UDP具有較低的延遲和較小的網(wǎng)絡(luò)開銷,適用于對實時性要求較高的應(yīng)用,如音頻、視頻流、實時游戲等。
  • TCP在保證可靠性的基礎(chǔ)上,會引入較高的延遲和額外的網(wǎng)絡(luò)開銷,適用于對數(shù)據(jù)完整性和順序性要求較高的應(yīng)用,如文件傳輸、Web請求等。

定時器

TCP 通過在發(fā)送時設(shè)置一個定時器來解決數(shù)據(jù)傳輸問題。如果當(dāng)定時器溢出時還沒收到確認(rèn),它就會重傳該數(shù)據(jù)。關(guān)鍵在于超時和重傳策略,即怎樣決定超時的時間間隔和如何確定重傳的頻率。在TCP中,常見的定時器有四種:重傳定時器、堅持定時器、?;疃〞r器、2MSL定時器。這四個定時器都有各自的具體作用。

  • 重傳定時器
    TCP是可靠的,因此,它對于發(fā)出去的信息,沒有得到正常ACK反饋的,都會啟動一個重傳機制。這個重傳機制使用一個重傳定時器,當(dāng)發(fā)現(xiàn)在規(guī)定時間內(nèi),沒有收到ACK,那么,重新發(fā)送消息,如果還沒有收到ACK,繼續(xù)重新發(fā)送消息…當(dāng)然,這每次繼續(xù)重新發(fā)送消息的時間間隔是不一樣的。一般默認(rèn),第一次重傳是發(fā)現(xiàn)超時后1s,第二次重傳是第一次重傳后3s,第三次是6s…

  • 堅持定時器
    堅持定時器是使用在一方滑動窗口為0之后,另外一方停止傳輸數(shù)據(jù),進(jìn)入堅持定時器的輪詢,直到滑動窗口不再為0了。

  • ?;疃〞r器
    這個就是我們經(jīng)常說的tcp的keepalive了。實際使用場景是在應(yīng)用層沒有數(shù)據(jù)進(jìn)行傳輸?shù)臅r候,一定時間(tcp_keepalive_time,默認(rèn)每2個小時)發(fā)送一次保持心跳的包,如果發(fā)送成功,則繼續(xù)保持端口活躍,如果沒有正常返回,則在指定次數(shù)內(nèi)(tcp_keepalive_probes,默認(rèn)是9次),指定間隔(tcp_keepalive_intvl,默認(rèn)是17s)發(fā)送心跳包。如果最后都沒有獲得正常的ACK,那么才算連接失敗。當(dāng)然,tcp是否需要提供keepalive機制,是有爭議的,我們可以為每個tcp連接設(shè)置是否啟用keepalive和啟用keepalive的各個指標(biāo)設(shè)置。

  • 2MSL定時器
    這個定時器用在TCP四次揮手之后,主動發(fā)起TCP斷開的一方需要保持2MSL的TIME_WAIT的狀態(tài)。這個保持的一方就會開啟2MSL定時器來計算TIME_WAIT的狀態(tài)保持時間。

tcp第三次握手中如果客戶端的ACK未送達(dá)服務(wù)器,會怎樣?

  • Server端:
    由于Server沒有收到ACK確認(rèn),因此會重發(fā)之前的SYN+ACK(默認(rèn)重發(fā)五次,之后自動關(guān)閉連接進(jìn)入CLOSED狀態(tài)),Client收到后會重新傳ACK給Server。

  • Client端,兩種情況:
    在Server進(jìn)行超時重發(fā)的過程中,如果Client向服務(wù)器發(fā)送數(shù)據(jù),數(shù)據(jù)頭部的ACK是為1的,所以服務(wù)器收到數(shù)據(jù)之后會讀取 ACK number,進(jìn)入 establish 狀態(tài)
    在Server進(jìn)入CLOSED狀態(tài)之后,如果Client向服務(wù)器發(fā)送數(shù)據(jù),服務(wù)器會以RST包(異常終止報文)應(yīng)答。

tcp如果已經(jīng)建立了連接,但客戶端出現(xiàn)了故障怎么辦?

服務(wù)器每收到一次客戶端的請求后都會重新復(fù)位一個計時器,時間通常是設(shè)置為2小時,若兩小時還沒有收到客戶端的任何數(shù)據(jù),服務(wù)器就會發(fā)送一個探測報文段,以后每隔75秒鐘發(fā)送一次。若一連發(fā)送10個探測報文仍然沒反應(yīng),服務(wù)器就認(rèn)為客戶端出了故障,接著就關(guān)閉連接。

初始序列號是什么?

TCP連接的一方A,隨機選擇一個32位的序列號(Sequence Number)作為發(fā)送數(shù)據(jù)的初始序列號(Initial Sequence Number,ISN),比如為1000,以該序列號為原點,對要傳送的數(shù)據(jù)進(jìn)行編號:1001、1002…三次握手時,把這個初始序列號傳送給另一方B,以便在傳輸數(shù)據(jù)時,B可以確認(rèn)什么樣的數(shù)據(jù)編號是合法的;同時在進(jìn)行數(shù)據(jù)傳輸時,A還可以確認(rèn)B收到的每一個字節(jié),如果A收到了B的確認(rèn)編號(acknowledge number)是2001,就說明編號為1001-2000的數(shù)據(jù)已經(jīng)被B成功接受。

什么時候應(yīng)該使用TCP?

當(dāng)對網(wǎng)絡(luò)通訊質(zhì)量有要求的時候,比如:整個數(shù)據(jù)要準(zhǔn)確無誤的傳遞給對方,這往往用于一些要求可靠的應(yīng)用,比如HTTP、HTTPS、FTP等傳輸文件的協(xié)議,POP、SMTP等郵件傳輸?shù)膮f(xié)議。

IP

IP協(xié)議是TCP/IP協(xié)議的核心,所有的TCP,UDP,IMCP,IGMP的數(shù)據(jù)都以IP數(shù)據(jù)格式傳輸。要注意的是,IP不是可靠的協(xié)議,這是說,IP協(xié)議沒有提供一種數(shù)據(jù)未傳達(dá)以后的處理機制,這被認(rèn)為是上層協(xié)議:TCP或UDP要做的事情。

在數(shù)據(jù)鏈路層中我們一般通過MAC地址來識別不同的節(jié)點,而在IP層我們也要有一個類似的地址標(biāo)識,這就是IP地址。

以下位IPv4的報頭:
HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),網(wǎng)絡(luò)協(xié)議,http,udp

HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),網(wǎng)絡(luò)協(xié)議,http,udp

名詞解析:

  • 4位版本:
    表示IP協(xié)議的版本號,當(dāng)前只有2個取值4(0100)和6(0110)。又稱lPv4和IPv6。我們當(dāng)前主要討論的是IPv4,至于IPv6,它還沒有普及。

  • 4位首部長度
    表示當(dāng)前IP協(xié)議的報頭有多長。IP協(xié)議報頭與TCP協(xié)議報頭類似,長度都是可變的。
    因為都帶有選項,這個選項可有可無,有的話有幾個?這些都是不確定的。所以我們通過4位首部長度來間接的描述出“選項”到底是多長?這一點和TCP相同。同時呢,4位值的是4個bit位,四個比特位的取值范圍0-15.因此,這里的首部長度的單位也是4字節(jié),比如:4個bit位 1111 == 15,實際表示的首部長就是60(4*15)字節(jié)。

  • 8位服務(wù)類型(T0s)
    TOS說是8位,其實只有4位是有效的,【3位優(yōu)先權(quán)字段(已經(jīng)棄用),4位Tos字段,和1位保留字段(必須置為0),】這4位TOS分別表示:最小延時,最大吞吐量,最高可靠性,最小成本。這四個機制是相互沖突的,同一時刻,只能選擇一個?!揪褪钦f這4個bit,同一時刻,只能有1位是1,其他位都是0】這里的 TOS相當(dāng)于就是在切換形態(tài)。(類似于動漫中的變身效果)

  • 16位總長度(字節(jié)數(shù))
    表示一次傳輸數(shù)據(jù)最大長度,包括報頭。

  • 16位標(biāo)識
    數(shù)據(jù)報太大了,超過64k,IP協(xié)議會自動拆包,以16位標(biāo)識區(qū)分,標(biāo)識相同說明這是一個包

  • 3位標(biāo)志
    最后的這個3位標(biāo)志位,其實只有一位好使。其作用就是描述當(dāng)前的包,是不是最后一個小包。
    當(dāng)這個標(biāo)志位為0的時候,表示還有后續(xù)的小包。當(dāng)這個標(biāo)志位為1的時候,表示當(dāng)前的這個數(shù)據(jù)包是最后一個包。也就是說:這3位標(biāo)志起到的作用就是結(jié)束標(biāo)記。

  • 13位片偏移
    13位片偏移區(qū)分在拆包后最終組裝的時候區(qū)分每個包的排序,以拼湊成完整的包
    通過這個13位片偏移,來描述多個包誰先誰后。片偏移的值越小,說明這個小包所在的位置越靠前。
    因為我們知道:網(wǎng)絡(luò)的環(huán)境是非常復(fù)雜的,可能存在先發(fā)后置的情況。雖然發(fā)送方、將一個大包拆成小包分別發(fā)送,但是這些小包到達(dá)的順序是無法確定的。所以我們接受方接收的順序,可能和發(fā)送方發(fā)送的順序不一樣。所以,通過這個片偏移量,我們就能確認(rèn)正確的組包順序。

  • 八位生存時間,TTL字段。這個字段規(guī)定該數(shù)據(jù)包在穿過多少個路由之后才會被拋棄。這里的單位不是s 或者ms,而是轉(zhuǎn)發(fā)次數(shù)。IP數(shù)據(jù)報被發(fā)送的時候,會有一個初始的TTL(比如常見的取值:128或者64)IP數(shù)據(jù)報每次經(jīng)過了一個路由器,該數(shù)據(jù)包的TTL數(shù)值就會減少1,當(dāng)該數(shù)據(jù)包的TTL成為零,它就會被自動拋棄。 這個字段的最大值也就是255,也就是說一個協(xié)議包也就在路由器里面穿行255次就會被拋棄了,根據(jù)系統(tǒng)的不同,這個數(shù)字也不一樣,一般是32或者是64。
    有這樣的機制,主要是因為有些包里面的IP地址,可能是永遠(yuǎn)也到不了的?!颈热纭胺瓑Α?,IP地址不存在】像這樣的包,不可能在網(wǎng)絡(luò)上無休止的轉(zhuǎn)發(fā)(占用硬件資源太多)。換個說法:正常情況下,IP的數(shù)據(jù)報都會在既定的 TTL內(nèi)到達(dá)目的IP。

  • 8位協(xié)議
    表示當(dāng)前傳輸層使用的協(xié)議是什么類型的。TCP或者是UDP都有不同的取值。通過這個取值來區(qū)分出當(dāng)前我們要把這個數(shù)據(jù)交給傳輸層之后,是交給哪一個協(xié)議來處理。

  • 16位檢驗和
    這就跟前面的 UDP/TCP的校驗和是一樣的,都是用來校驗數(shù)據(jù)是否正確?!緮?shù)據(jù)量/內(nèi)容】

  • 32位源IP地址
    源IP,表示:發(fā)件人地址?!景l(fā)送方主機地址】

  • 32位目的P地址
    目的IP,表示:收件人地址?!窘邮辗街鳈C地址】

IP協(xié)議最重要的一個功能:進(jìn)行轉(zhuǎn)發(fā)。到底從哪里轉(zhuǎn)發(fā)到哪里?
我們就可以通過IP地址來去描述。對于IPv4來說,一個IP地址本質(zhì)上是32位的整數(shù)(整數(shù)==4byte == 32bit)通過會使用“點分十進(jìn)制”這樣的方式來表示這個IP地址。點分十進(jìn)制:就是用三個小數(shù)點,把32bit位分成4部分,每個部分一個字節(jié)。每個部分的取值:0-255

8位服務(wù)類型T0S補充:
IP協(xié)議可以迪過T0S來進(jìn)行切換形態(tài)。

  • 最小延時:從主機A到主機B之間,取一條時間最短的路徑
  • 最大吞吐量:從主機A到主機B之間,取一條路徑,它的傳輸帶寬最高的。
  • 最高可靠性:從主機A到主機B之間,取一條最不容易丟包的路徑
  • 最小成本:從主機A到主機B之間,取一條開銷最小的路徑

此時,我們就可以實際需要,來選擇一條合適的路徑IP協(xié)議能規(guī)劃2點之間一條比較合適的路徑,什么叫合適?
合適,其實就是上面的4位TOS(最小延時,最大吞吐量,最高可能性,最小成本),看你門選的哪一個!如果選擇最小延時:認(rèn)為花費時間最短的路徑,就是合適的路徑。如果選擇最大吞吐量:認(rèn)為傳輸帶寬最高的路徑,就是合適的路徑。所以這個合適,是和TOS是密切相關(guān)的。雖然講了這么多,但是在日常開發(fā)中,還是很少關(guān)注這個TOS內(nèi)容,了解即可。

16位總長度(字節(jié)數(shù))補充:

看到16位,我們就應(yīng)該反應(yīng)過來16位的最大長度為64k。那么,難道說我們的IP協(xié)議包最長也就只能表示64k嘛?
確實如此,因此,單個IP數(shù)據(jù)報最大長度確實不能超過64 k。那如果我們想要構(gòu)造一個更長的數(shù)據(jù)報(搭載的載荷部分已經(jīng)超過64k),怎么辦?
處理方式:其實 IP協(xié)議自身實現(xiàn)了分包和組包這樣的操作。前面在講UDP的時候,也講了UDP想要傳輸一個更大的數(shù)據(jù),需要程序員在應(yīng)用層代碼上手動實現(xiàn)分包和組包?,F(xiàn)在,如果是IP協(xié)議的話,其實它里面自己已經(jīng)實現(xiàn)好了分包和組包。

IP報頭解析

IP協(xié)議主要完成兩方面工作:

  1. 地址管理
  2. 路由選擇;路由選擇,也就是規(guī)劃路徑。當(dāng)兩個設(shè)備之間,要找出一條通道,能夠完成傳輸?shù)倪^程。要想找出通道的前提是:要先認(rèn)識路!

IP數(shù)據(jù)報中的目的IP地址,就表示了這個包要發(fā)到那里去。這個目的地址,如果當(dāng)前路由器直接認(rèn)識,就直接告訴你了。如果當(dāng)前路由器不認(rèn)識,就會告訴你一個大概的方向。讓你走到下一個路由器的時候,再來問路。依次往后走,其實也是一個離目標(biāo)越來越近的過程。近到一定的程度,總會遇到一個認(rèn)識這個地址的路由器。于是就可以具體的轉(zhuǎn)發(fā)過去了。

這就是路由選擇的一個大致的過程。有的時候,不光遇到了一個認(rèn)識這個地址的路由器。并且,它還認(rèn)識多條通往這個IP地址的路。這個時候,就可以選擇一個更合適的路了。
其實“路由選擇”就是一個“問路”的過程。如果你接下來不知道往哪走,沒關(guān)系!每到一個路由器,它都會告訴你一個大概的位置。根據(jù)這個位置去走,離目的IP就越近。走著走著,總會遇到一個認(rèn)識目的IP的路由器。此時,就可以完成一個后續(xù)的轉(zhuǎn)發(fā)。

什么叫做路由器“認(rèn)識”這個IP地址?
其實在路由器內(nèi)部維護(hù)了一個數(shù)據(jù)結(jié)構(gòu)【路由表】,路由表里面就記錄了一些網(wǎng)段信息(網(wǎng)絡(luò)號),以及每個網(wǎng)絡(luò)號對應(yīng)的網(wǎng)絡(luò)接口。目的IP,就在這些網(wǎng)絡(luò)號中匹配。判斷目的IP是不是就是當(dāng)前網(wǎng)段里面的;如果匹配,你就根據(jù)它的網(wǎng)絡(luò)號,走對應(yīng)的網(wǎng)絡(luò)接口。網(wǎng)絡(luò)接口:其實就對應(yīng)到路由器里面具體的端口,等于告訴你接下來,你就往這條路走就行了。
路由器有很多端口,有的WAN口,有的LAN口。(有的路由器甚至還有更多的接口)然后,這里面就會告訴你:當(dāng)前這條路是沿著WAN口,還是LAN口走。告訴我們走那條路更合適。這里面關(guān)鍵就是:路由器里面有一個路由表的數(shù)據(jù)結(jié)構(gòu)。
路由表本身,其實并不復(fù)雜。主要就是由網(wǎng)絡(luò)號+網(wǎng)絡(luò)接口組成的。
復(fù)雜的是:路由表是怎么來的?這個是有一系列專門的路由表生成算法。
就是可以自動生成一波,還可以手動配置【不做過多的深究,有興趣的,自行了解】

學(xué)習(xí)原博客

HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),網(wǎng)絡(luò)協(xié)議,http,udp

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

物理層負(fù)責(zé)0、1比特流與物理設(shè)備電壓高低、光的閃滅之間的互換。
數(shù)據(jù)鏈路層負(fù)責(zé)將0、1序列劃分為數(shù)據(jù)幀從一個節(jié)點傳輸?shù)脚R近的另一個節(jié)點,這些節(jié)點是通過MAC來唯一標(biāo)識的(MAC,物理地址,一個主機會有一個MAC地址)。

數(shù)據(jù)鏈路層主要的協(xié)議,叫做“以太網(wǎng)”。像平時我們插的網(wǎng)線,就叫做“以太網(wǎng)線”。至于 以太網(wǎng)的協(xié)議,我們不做過多討論。

以太網(wǎng),這個協(xié)議不僅僅規(guī)定了數(shù)據(jù)鏈路層的內(nèi)容。也規(guī)定了物理層的內(nèi)容。以太網(wǎng),是一個橫跨兩層的協(xié)議。

HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),網(wǎng)絡(luò)協(xié)議,http,udp

目的地址和源地址:通過6個字節(jié)來表示。這個就要比 IPv4(4byte)的更長。大概長了6萬多倍。這里的地址稱為mac地址,mac地址做到了每個設(shè)備/每個網(wǎng)卡都是唯一的。mac地址,是在網(wǎng)卡出廠的時候就被寫死了。這個時候,我們就能通過mac地址來區(qū)分唯一的主機。

物理地址/mac地址,也不是不能改。有些網(wǎng)卡是支持手動配置的。

有一個問題:已經(jīng)有IP地址,為什么還要mac/物理地址?這其實是一個美好的誤會。
當(dāng)年的網(wǎng)絡(luò)層協(xié)議和數(shù)據(jù)鏈路層協(xié)議,是各自獨立研發(fā)出來的。這就導(dǎo)致mac地址和IP地址,就有點重復(fù)了。
按理來說:一套地址就夠了。但是,都研發(fā)出來了,就一起用唄。現(xiàn)在的現(xiàn)狀,就是當(dāng)前的mac地址和IP地址同時使用。但是表示不同的功能:

  • IP用來表一次傳輸過程中的起點和終點。如果不考慮NAT的情況,一個IP數(shù)據(jù)報中的源IP和的IP是固定的。
  • mac用來表示傳輸過程中,任意兩個相鄰節(jié)點之間的地址。一個以太網(wǎng)數(shù)據(jù)幀,在每次轉(zhuǎn)發(fā)的過程中,源mac和目的mac都會改變。

類型 : 類型:描述后面的數(shù)據(jù)搭載的是什么樣的數(shù)據(jù)。類型取不同的值,表示后面的數(shù)據(jù)搭載不同類型的數(shù)據(jù)。比如:類型取值為0800,那么后面的數(shù)據(jù)就是一個完整的IP數(shù)據(jù)報【一般情況】

如果是0806,那么后面的數(shù)據(jù)就是一個ARP請求/應(yīng)答。如果是8035,那么后面的數(shù)據(jù)就是一個RARP請求/應(yīng)答;這兩個是屬于特殊情況!

HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),網(wǎng)絡(luò)協(xié)議,http,udp

MUT

MTU:一個以太網(wǎng)數(shù)據(jù)幀能夠承載的數(shù)據(jù)范圍,取值為46-1500之間。

其中的1500,我們將其稱之為 MTU:一個以太網(wǎng)數(shù)據(jù)幀能夠承載的數(shù)據(jù)范圍。這個范圍取決于硬件設(shè)備。因為以太網(wǎng)是和硬件是屬于有密切關(guān)系的。換句話來說:以太網(wǎng)要求的 MTU的值就是1500。如果是其他的硬件設(shè)備,對應(yīng)的數(shù)據(jù)鏈路層協(xié)議,可能又不一樣。不同的數(shù)據(jù)鏈路層協(xié)議,它們的MTU值也是不一樣的。

我們可以這樣簡單的去理解:其實數(shù)據(jù)鏈路層鎖考慮的事情,就是兩個相鄰的節(jié)點如何進(jìn)行傳輸。具體考慮到怎么傳輸,就需要考慮到“交通工具”。具體的的過程中,不同的“交通工具”,能夠搭載的數(shù)據(jù)量是不相同的。【其實也好理解,一個騎小電驢的快遞員和一個開貨車的快遞員,肯定是開貨車的快遞員,貨物多啊。】

如果數(shù)據(jù)超過了MTU怎么辦?注意!我們不是在IP層能夠分包嘛?
其實,IP層的分包,其實不是給IP報頭的64k準(zhǔn)備的,更多的是為了適應(yīng)數(shù)據(jù)鏈路層的MTU。尤其是像以太網(wǎng)這種MTU比較短的,是很容易觸發(fā)分包的情況。

所以,MTU,其實是受限于硬件的。正因為受限于硬件,才對軟件提出了更高的要求。所以,我們在IP層,才提了分包的操作。保證能對下層的這些限制,都能夠進(jìn)行一個處理和應(yīng)用。

MTU對UDP協(xié)議的影響

一旦UDP攜帶的數(shù)據(jù)超過1472(1500 - 20 (IP首部)–8(UDP首部)),那么就會在網(wǎng)絡(luò)層分成多個IP數(shù)據(jù)報。這多個IP數(shù)據(jù)報有任意一個丟失,都會引起接收端網(wǎng)絡(luò)層重組失敗。那么這就意味著,如果UDP數(shù)據(jù)報在網(wǎng)絡(luò)層被分片,整個數(shù)據(jù)被丟失的概率就大大增加了。

主要的影響:分包之后,會導(dǎo)致UDP的丟包概率提升。并且UDP自身并沒有可靠性的機制,所以多少都會對UDP產(chǎn)生影響

一旦 UDP 攜帶的數(shù)據(jù) 超過1472(1500-20(IP首部)-8(UDP首部)),那么 UDP 數(shù)據(jù)就會在網(wǎng)絡(luò)層被分成多個 IP 數(shù)據(jù)報既:發(fā)送方 IP 層就需要將數(shù)據(jù)包分成若干片,而接收方 IP 層就需要進(jìn)行數(shù)據(jù)報的重組。更嚴(yán)重的是,如果使用 UDP 協(xié)議,當(dāng) IP 層組包發(fā)生錯誤,那么包就會被丟棄。接收方無法重組數(shù)據(jù)報,將導(dǎo)致丟棄整個 IP 數(shù)據(jù)報。

MTU對于TCP協(xié)議的影響

TCP的一個數(shù)據(jù)報也不能無限大,還是受制于MTU。TCP的單個數(shù)據(jù)報的最大消息長度,稱為MSS (Max Segment Size);
TCP在建立連接的過程中,通信雙方會進(jìn)行MSS協(xié)商。最理想的情況下,MSS的值正好是在IP不會被分片處理的最大長度(這個長度仍然是受制于數(shù)據(jù)鏈路層的MTU)。
雙方在發(fā)送’SYN’的時候會在TCP頭部寫入自己能支持的MSS值。然后雙方得知對方的MSS值之后,選擇較小的作為最終MSS。MSS的值就是在TCP首部的40字節(jié)變長選項中(kind=2)。
MSS:TCP中,在IP不分包的前提下,最多搭載多少載荷/數(shù)據(jù)。MSS的值,取決于MTU,也取決于TCP 和IP的報頭(報頭都是可以變長的)

MTU 通過限制 MSS(單個數(shù)據(jù)報的最大消息長度) 的取值,來限制單個 TCP 包的長度

MTU 和 MSS的關(guān)系
MTU:最大傳輸單元,由不同的數(shù)據(jù)鏈路層對應(yīng)物理層產(chǎn)生的(硬件規(guī)定),以太網(wǎng)的MTU=1500
MSS:最大分節(jié)大小,為 TCP 數(shù)據(jù)包每次傳輸?shù)淖畲髷?shù)據(jù)分段大小
MSS 的取值受限于 MTU

ARP協(xié)議

ARP 協(xié)議 英文名叫作:“Address Resolution Protocol”——地址解析協(xié)議。所謂“地址解析”就是主機在發(fā)送幀前將目的邏輯地址

轉(zhuǎn)換成目的物理地址的過程。在使用 TCP/IP 協(xié)議 的以太網(wǎng)中,ARP 協(xié)議完成將 IP 地址映射到 MAC 地址的過程。

在TCP/IP協(xié)議模型中,一共有五層,也就是物理層、數(shù)據(jù)鏈路層、網(wǎng)絡(luò)層、傳輸層、應(yīng)用層。在數(shù)據(jù)鏈路層中的地址稱為MAC地址或者叫作 以太網(wǎng)地址(Ethernet address)。

什么是MAC地址?
我這里稍微講解一下MAC地址,MAC地址全稱叫做 MAC(Media Access Control,介質(zhì)訪問控制)地址,在數(shù)據(jù)鏈路層傳輸,一共48位,每一個網(wǎng)卡對應(yīng)了一個全球唯一的MAC地址,在網(wǎng)線中傳輸,就是通過MAC地址來傳輸?shù)侥愕碾娔X網(wǎng)卡上。

什么是IP地址?
IP地址,網(wǎng)絡(luò)協(xié)議地址(Internet Protocol address)的簡稱。屬于網(wǎng)絡(luò)層,在網(wǎng)絡(luò)中唯一標(biāo)識一臺主機,一共32位,在網(wǎng)絡(luò)層和傳輸層傳輸數(shù)據(jù)包時,就是用IP來標(biāo)識進(jìn)行傳輸?shù)摹?/p>

為什么要用ARP協(xié)議呢?
如果你知道了MAC地址,又知道了IP地址,那么問題就來了,網(wǎng)絡(luò)層只識別IP地址,而數(shù)據(jù)鏈路層則只識別MAC地址。所以我們需要一個映射,來將MAC地址和IP地址對應(yīng)起來,這樣我們通過MAC地址知道了IP地址,通過IP地址也就知道了MAC地址。這個映射就是ARP協(xié)議,將IP地址映射到MAC地址,而RARP,也就是反向地址解析協(xié)議,也就是把MAC地址映射成IP地址,這樣的話,IP地址和MAC地址也就對應(yīng)起來了。

ARP協(xié)議具體使用:

試想一下,有一個交換機很多主機,其中包括主機A和主機B?,F(xiàn)在主機A需要將一個數(shù)據(jù)包通過交換機傳輸給主機B,現(xiàn)在主機A已經(jīng)知道了主機B的IP地址了,但不知道主機B的MAC地址,而交換機是通過網(wǎng)線傳輸給主機B的,需要知道主機B的MAC地址,這時候交換機就會使用ARP協(xié)議來獲取主機B的MAC地址了。

ARP 運行過程可分為如下步驟:

  • 一、首先,發(fā)送端必須知道目的端的 IP 地址,也就是主機A必須知道主機B的IP地址了。

  • 二、 IP 要求 ARP 創(chuàng)建一個 ARP 請求報文,其中包含了主機A的MAC地址、主機A的 IP 地址 和 主機B的 IP 地址。主機B的MAC地址不知道,則會用 0 填充,也就是此時主機B的MAC地址為全0。

  • 三、將報文傳遞到數(shù)據(jù)鏈路層,并在該層中用主機A的MAC地址作為源地址,用物理廣播地址作為目的地址,將其封裝在一個幀中,(全0或者全F的MAC地址為廣播地址)。

  • 四、因為該幀中包含了一個廣播目的地址(全F的MAC地址),所以同一鏈路中的每個主機或路由器都接收到這 個幀。所有接收到該幀的主機都將其傳遞到 ARP 層進(jìn)行處理。除了主機B以外的,因為IP不是自己的,所以其他主機都丟棄該報文,只有主機B會接受該報文。

  • 五、主機B用一個包含它的MAC地址的 ARP 應(yīng)答報文做出響應(yīng),該報文的源IP地址、源MAC地址都為主機B的地址,目的IP地址和目的IP地址為主機A的地址,并對該報文進(jìn)行單播傳回給主機A。

  • 六、主機A接收到這個應(yīng)答報文,就知道了主機B的MAC地址。

HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),網(wǎng)絡(luò)協(xié)議,http,udp

這就是ARP傳輸?shù)牡览砹?,通過ARP協(xié)議來已知IP地址來獲取MAC地址。

已經(jīng)知道了以后,ARP會建立ARP緩沖表來存儲IP地址和MAC地址,就不需要再通過廣播和單播來傳了。

ARP 高速緩存
在真正的協(xié)議實現(xiàn)中,并不是每次發(fā)送 IP 報文前都需要發(fā)送 ARP 請求報文來獲取目的 MAC 地址(像上面這來獲?。6侵痹诖蠖鄶?shù)的系統(tǒng)中都存在著一個 ARP 緩存表。

ARP 緩存表記錄著一段時間內(nèi)曾經(jīng)獲取過的 MAC 地址和 IP 地址的映射關(guān)系。所以發(fā)送 IP 數(shù)據(jù)報前先對 ARP 緩存表進(jìn)行查找,查看目的 MAC 地址是否存在于緩存表中, 如果存在,則不需要發(fā)送 ARP 請求報文而直接使用此地址進(jìn)行 IP 數(shù)據(jù)包的發(fā)送。如果不存 在,則發(fā)送 ARP 請求報文,在收到 ARP 應(yīng)答報文之后,使用應(yīng)答報文中的目的 MAC 地址發(fā)送 IP 數(shù)據(jù)包,并將目的 MAC 地址存于 ARP 緩存表中供以后使用。

ARP協(xié)議原文

網(wǎng)卡接收數(shù)據(jù)流程

參考另一篇博客

網(wǎng)卡(Network Interface Card,簡稱NIC),也稱網(wǎng)絡(luò)適配器,是電腦與局域網(wǎng)相互連接的設(shè)備。

以往,從網(wǎng)卡的 I/O 區(qū)域,包括 I/O 寄存器或 I/O 內(nèi)存中讀取數(shù)據(jù),這都要 CPU 親自去讀,然后把數(shù)據(jù)放到 RAM 中,也就占用了 CPU 的運算資源。直到出現(xiàn)了 DMA 技術(shù),其基本思想是外設(shè)和 RAM 之間開辟直接的數(shù)據(jù)傳輸通路。一般情況下,總線所有的工作周期(總線周期)都用于 CPU 執(zhí)行程序。DMA 控制就是當(dāng)外設(shè)完成數(shù)據(jù) I/O 的準(zhǔn)備工作之后,會占用總線的一個工作周期,和 RAM 直接交換數(shù)據(jù)。這個周期之后,CPU 又繼續(xù)控制總線執(zhí)行原程序。如此反復(fù)的,直到整個數(shù)據(jù)塊的數(shù)據(jù)全部傳輸完畢,從而解放了 CPU。

大致需要以下幾個步驟:

  • 網(wǎng)卡收到數(shù)據(jù)包。
  • 將數(shù)據(jù)包從網(wǎng)卡硬件緩存轉(zhuǎn)移到服務(wù)器內(nèi)存中。
  • 通知內(nèi)核處理。
  • 經(jīng)過TCP/IP協(xié)議逐層處理。
  • 應(yīng)用程序通過read()從socket buffer讀取數(shù)據(jù)。

首先,內(nèi)核在 RAM 中為收發(fā)數(shù)據(jù)建立一個環(huán)形的緩沖隊列,通常叫 DMA 環(huán)形緩沖區(qū),又叫 BD(Buffer descriptor)表。

內(nèi)核將這個緩沖區(qū)通過 DMA 映射,把這個隊列交給網(wǎng)卡;

網(wǎng)卡收到數(shù)據(jù),先把數(shù)據(jù)臨時存放到 Rx FIFO 中,繞后通過 DMA 的方式把Rx FIFO 的數(shù)據(jù)包放到RAM 的環(huán)形緩沖區(qū)中。然后,網(wǎng)卡驅(qū)動向系統(tǒng)產(chǎn)生一個硬中斷,內(nèi)核收到這個硬中斷后,啟動軟中斷,在軟中斷中關(guān)閉硬中斷,告訴 CPU 后續(xù)再由數(shù)據(jù)不用產(chǎn)生硬中斷通知CPU,然后內(nèi)核線程在軟中斷中從喚醒緩沖區(qū)取出數(shù)據(jù),上傳到協(xié)議棧中

硬中斷 軟中斷

網(wǎng)卡接收數(shù)據(jù)流程原文

零拷貝

相關(guān)問題

一個 IP 報文經(jīng)過路由器處理后,若 TTL 字段值變?yōu)?0,則路由器會進(jìn)行的操作是(向IP報文的源地址發(fā)送一個出錯信息,并丟棄該報文)

當(dāng) IP 報文從一個網(wǎng)絡(luò)轉(zhuǎn)發(fā)到另一個網(wǎng)絡(luò)時MAC 地址會改變,但 IP 地址不變;IP報文從一個網(wǎng)絡(luò)轉(zhuǎn)發(fā)到另一個網(wǎng)絡(luò)時,IP地址是不變的,而在鏈路層是一段鏈路一段鏈路轉(zhuǎn)發(fā)的,MAC地址會改變

IPv4 的頭部是變長的,IPv6 的頭部是定長的;IPv6 中的 HOP Limit 字段作用類似于 IPv4 中的 TTL 字段;IPv6 中的 Traffic Class 字段作用類似于 IPv4 中的 Tos 字段

IP數(shù)據(jù)報首部中IHL (Internet首部長度)字段的最小值 5,最大值 15

UDP/TCP 包的大小限制

TCP會粘包、UDP永遠(yuǎn)不會粘包

發(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),一條消息有多少字節(jié)對應(yīng)用程序是不可見的,因此TCP協(xié)議是面向流的協(xié)議,這也是容易出現(xiàn)粘包問題的原因。

而UDP是面向消息的協(xié)議,每個UDP段都是一條消息,應(yīng)用程序必須以消息為單位提取數(shù)據(jù),不能一次提取任意字節(jié)的數(shù)據(jù),這一點和TCP是很不同的。怎樣定義消息呢?可以認(rèn)為對方一次性write/send的數(shù)據(jù)為一個消息,需要明白的是當(dāng)對方send一條信息的時候,無論底層怎樣分段分片,TCP協(xié)議層會把構(gòu)成整條消息的數(shù)據(jù)段排序完成后才呈現(xiàn)在內(nèi)核緩沖區(qū)。

粘包問題主要出現(xiàn)在用TCP協(xié)議傳輸中才會出現(xiàn)的問題,UDP不會出現(xiàn),因為TCP傳輸中他會服務(wù)端會一次性把所有東西一并丟入緩存區(qū),而讀取的內(nèi)容大小有時候沒法準(zhǔn)確的做到一一讀取,所有會存在粘包。
而UDP他傳輸?shù)臅r候是吧一個個內(nèi)容丟過去,不管客戶端能否完全接受到內(nèi)容他都會接受他制定大小的內(nèi)容,而內(nèi)容大于他接受設(shè)定的大小時候多余的東西會被丟到

產(chǎn)生黏包的兩種情況 :

  • 發(fā)送端需要等待緩沖區(qū)滿了才將數(shù)據(jù)發(fā)送出去, 如果發(fā)送數(shù)據(jù)的時間間隔很短, 數(shù)據(jù)很小, 就會合到一起, 產(chǎn)生黏包
  • 接收方?jīng)]有及時接收緩沖區(qū)的包, 造成多個包一起接收, 如果服務(wù)端一次只接收了一小部分, 當(dāng)服務(wù)端下次想接收新的數(shù)據(jù)的時候, 拿到的還是上次緩沖區(qū)里剩余的內(nèi)容

注意:粘包不一定發(fā)生,如果發(fā)生了:可能是在客戶端已經(jīng)粘了??蛻舳藳]有粘,可能是在服務(wù)端粘了。

例如基于tcp的套接字客戶端往服務(wù)端上傳文件,發(fā)送時文件內(nèi)容是按照一段一段的字節(jié)流發(fā)送的,在接收方看了,根本不知道該文件的字節(jié)流從何處開始,在何處結(jié)束。

此外,發(fā)送方引起的粘包是由TCP協(xié)議本身造成的,TCP為提高傳輸效率,發(fā)送方往往要收集到足夠多的數(shù)據(jù)后才發(fā)送一個TCP段。若連續(xù)幾次需要send的數(shù)據(jù)都很少,通常TCP會根據(jù)優(yōu)化算法把這些數(shù)據(jù)合成一個TCP段后一次發(fā)送出去,這樣接收方就收到了粘包數(shù)據(jù)。

所謂粘包問題主要還是因為接收方不知道消息之間的界限,不知道一次性提取多少字節(jié)的數(shù)據(jù)所造成的。

  1. TCP(transport control protocol,傳輸控制協(xié)議)是面向連接的,面向流的,提供高可靠性服務(wù)。收發(fā)兩端(客戶端和服務(wù)器端)都要有一一成對的socket,因此,發(fā)送端為了將多個發(fā)往接收端的包,更有效的發(fā)到對方,使用了優(yōu)化方法(Nagle算法),將多次間隔較小且數(shù)據(jù)量小的數(shù)據(jù),合并成一個大的數(shù)據(jù)塊,然后進(jìn)行封包。這樣,接收端,就難于分辨出來了,必須提供科學(xué)的拆包機制。 即面向流的通信是無消息保護(hù)邊界的。

  2. UDP(user datagram protocol,用戶數(shù)據(jù)報協(xié)議)是無連接的,面向消息的,提供高效率服務(wù)。不會使用塊的合并優(yōu)化算法,, 由于UDP支持的是一對多的模式,所以接收端的skbuff(套接字緩沖區(qū))采用了鏈?zhǔn)浇Y(jié)構(gòu)來記錄每一個到達(dá)的UDP包,在每個UDP包中就有了消息頭(消息來源地址,端口等信息),這樣,對于接收端來說,就容易進(jìn)行區(qū)分處理了。 即面向消息的通信是有消息保護(hù)邊界的。

  3. TCP是基于數(shù)據(jù)流的,于是收發(fā)的消息不能為空,這就需要在客戶端和服務(wù)端都添加空消息的處理機制,防止程序卡住,而udp是基于數(shù)據(jù)報的,即便是你輸入的是空內(nèi)容(直接回車),那也不是空消息,udp協(xié)議會幫你封裝上消息頭,實驗略
    udp的recvfrom是阻塞的,一個recvfrom(x)必須對唯一一個sendinto(y),收完了x個字節(jié)的數(shù)據(jù)就算完成,若是y>x數(shù)據(jù)就丟失,這意味著udp根本不會粘包,但是會丟數(shù)據(jù),不可靠。

tcp的協(xié)議數(shù)據(jù)不會丟,沒有收完包,下次接收,會繼續(xù)上次繼續(xù)接收,發(fā)送端總是在收到ack時才會清除緩沖區(qū)內(nèi)容。數(shù)據(jù)是可靠的,但是會粘包。

解決粘包問題的方式

TCP/UDP對比

HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),網(wǎng)絡(luò)協(xié)議,http,udp

面向報文的傳輸方式是應(yīng)用層交給UDP多長的報文,UDP就照樣發(fā)送,即一次發(fā)送一個報文。因此,應(yīng)用程序必須選擇合適大小的報文。若報文太長,則IP層需要分片,降低效率。若太短,會是IP太小。

面向字節(jié)流的話,雖然應(yīng)用程序和TCP的交互是一次一個數(shù)據(jù)塊(大小不等),但TCP把應(yīng)用程序看成是一連串的無結(jié)構(gòu)的字節(jié)流。TCP有一個緩沖,當(dāng)應(yīng)用程序傳送的數(shù)據(jù)塊太長,TCP就可以把它劃分短一些再傳送。

學(xué)習(xí)博客

TCP/IP協(xié)議圖解及演化過程

OSI網(wǎng)絡(luò)七層模型

面試高頻—TCP/IP十大問題文章來源地址http://www.zghlxwxcb.cn/news/detail-847815.html

到了這里,關(guān)于HTTP/UDP/TCP/IP網(wǎng)絡(luò)協(xié)議的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 網(wǎng)絡(luò)基礎(chǔ)2【HTTP、UDP、TCP】

    網(wǎng)絡(luò)基礎(chǔ)2【HTTP、UDP、TCP】

    目錄 一.應(yīng)用層 1.協(xié)議 2.網(wǎng)絡(luò)版計算器 3.HTTP協(xié)議 (1)了解url和http (2)http的用處 (3)urlencode和urldecode (4)http協(xié)議格式 4.HTTPS協(xié)議 ?(1)加密 (2)為什么要加密 (3)常見的加密方式 (4)數(shù)據(jù)摘要(數(shù)據(jù)指紋) (5)加密方案 (6)證書 (7)數(shù)字簽名(數(shù)據(jù)簽名) (

    2023年04月25日
    瀏覽(20)
  • 網(wǎng)絡(luò)編程——TCP/IP協(xié)議族(IP協(xié)議、TCP協(xié)議和UDP協(xié)議……)

    1、IP協(xié)議簡介 IP協(xié)議又稱 網(wǎng)際協(xié)議 特指為實現(xiàn)在一個相互連接的網(wǎng)絡(luò)系統(tǒng)上從源地址到目的地傳輸數(shù)據(jù)包(互聯(lián)網(wǎng)數(shù)據(jù)包)所提供必要功能的協(xié)議,是網(wǎng)絡(luò)層中的協(xié)議。 2、特點 不可靠 :它不能保證IP數(shù)據(jù)包能成功地到達(dá)它的目的地,僅提供盡力而為的傳輸服務(wù) 無連接 :IP 并不

    2024年02月13日
    瀏覽(113)
  • 網(wǎng)絡(luò)編程 tcp udp http編程流程 網(wǎng)絡(luò)基礎(chǔ)知識

    網(wǎng)絡(luò)編程 tcp udp http編程流程 網(wǎng)絡(luò)基礎(chǔ)知識

    OSI分層:應(yīng)用層 表示層 會話層 傳輸層 網(wǎng)絡(luò)層 數(shù)據(jù)鏈路層 物理層 tcp/ip: 應(yīng)用層 傳輸層 網(wǎng)絡(luò)層 數(shù)據(jù)鏈路 ip地址:唯一標(biāo)識一臺主機 ipv4 32位 ipv6 128位 尋址 可以反映物理上的一個變化 MAC地址:48 固化在計算機中 ip地址又兩部分構(gòu)成:網(wǎng)絡(luò)號+主機號 端口號:標(biāo)識一個應(yīng)用程序

    2024年02月13日
    瀏覽(38)
  • 一文徹底搞懂TCP/IP、UDP、FTP、HTTP、HTTPS的基本原理

    基本原理:TCP/IP是一組用于實現(xiàn)網(wǎng)絡(luò)通信的協(xié)議族,它是互聯(lián)網(wǎng)的基礎(chǔ)協(xié)議。TCP/IP協(xié)議族由兩個主要協(xié)議組成:TCP(Transmission Control Protocol,傳輸控制協(xié)議)和IP(Internet Protocol,網(wǎng)際協(xié)議)。 TCP(Transmission Control Protocol):TCP是一種面向連接的、可靠的、基于字節(jié)流的傳輸層

    2024年03月08日
    瀏覽(39)
  • Wireshark抓取網(wǎng)卡協(xié)議分析(TCP,UDP,ARP,DNS,DHCP,HTTP超詳細(xì)版本)

    Wireshark抓取網(wǎng)卡協(xié)議分析(TCP,UDP,ARP,DNS,DHCP,HTTP超詳細(xì)版本)

    使用wireshark工具抓取ping命令操作 選擇本機網(wǎng)卡WLAN,點擊開始,開始抓包 在數(shù)據(jù)列表區(qū)中選取TCP協(xié)議,在數(shù)據(jù)詳細(xì)區(qū)中顯示出其詳細(xì)信息 (1)Frame: 物理層的數(shù)據(jù)幀概況 (2)Ethernet II: 數(shù)據(jù)鏈路層以太網(wǎng)幀頭部信息 (3)Internet Protocol Version 6: 互聯(lián)網(wǎng)層IP包頭部信息 (4)Tra

    2024年02月08日
    瀏覽(21)
  • API 接口主流協(xié)議有哪些?如何創(chuàng)建 HTTP/HTTP、WebSocket/WebSockets、TCP/UDP、gRPC、SOAP、Dubbo/HSF 等不同協(xié)議?

    API 接口主流協(xié)議有哪些?如何創(chuàng)建 HTTP/HTTP、WebSocket/WebSockets、TCP/UDP、gRPC、SOAP、Dubbo/HSF 等不同協(xié)議?

    API 接口協(xié)議繁多,不同的協(xié)議有著不同的使用場景。70% 互聯(lián)網(wǎng)應(yīng)用開發(fā)者日常僅會接觸到最通用的 HTTP 協(xié)議,相信大家希望了解更多其他協(xié)議的信息。我們今天會給大家介紹各種 API 接口主流協(xié)議和他們之間的關(guān)系。 接口協(xié)議分成兩類: 傳輸層協(xié)議和應(yīng)用層協(xié)議。 傳輸層協(xié)

    2023年04月21日
    瀏覽(45)
  • 【Linux網(wǎng)絡(luò)】TCP UDP socket HTTP webSocket之間的區(qū)別

    【Linux網(wǎng)絡(luò)】TCP UDP socket HTTP webSocket之間的區(qū)別

    目錄 一、OSI TCP/IP模型 二、幾者之間的關(guān)系 三、HTTP 四、Socket 五、WebSocket 5.1、WebSocket 優(yōu)點 首先我們要了解OSI七層模型,和預(yù)支對應(yīng)的TCP/IP 四層的模型。 ? ? 用下面的圖可以看出,TCP? UDP 工作在傳輸層,而 HTTP? WebSocket 工作在應(yīng)用層,但socket不屬于七層模型中的任何一層,

    2024年02月11日
    瀏覽(33)
  • Java網(wǎng)絡(luò)編程之IP,端口號,通信協(xié)議(UDP,TCP)

    Java網(wǎng)絡(luò)編程之IP,端口號,通信協(xié)議(UDP,TCP)

    ① C/S :客戶端/服務(wù)器 在用戶本地需要下載安裝客戶端程序,在遠(yuǎn)程有一個服務(wù)器端程序。 優(yōu)點:畫面精美,用戶體驗好 缺點:用戶需要下載更新 ② B/S :瀏覽器/服務(wù)器 只需要一個瀏覽器,用戶通過指定網(wǎng)址訪問對應(yīng)的服務(wù)器。 優(yōu)點:不需要開發(fā)客戶端,只需要頁面+服務(wù)

    2024年02月03日
    瀏覽(96)
  • Java中網(wǎng)絡(luò)的基本介紹。網(wǎng)絡(luò)通信,網(wǎng)絡(luò),ip地址,域名,端口,網(wǎng)絡(luò)通信協(xié)議,TCP/IP傳輸過程,網(wǎng)絡(luò)通信協(xié)議模型,TCP協(xié)議,UDP協(xié)議

    Java中網(wǎng)絡(luò)的基本介紹。網(wǎng)絡(luò)通信,網(wǎng)絡(luò),ip地址,域名,端口,網(wǎng)絡(luò)通信協(xié)議,TCP/IP傳輸過程,網(wǎng)絡(luò)通信協(xié)議模型,TCP協(xié)議,UDP協(xié)議

    - 網(wǎng)絡(luò)通信 概念:網(wǎng)絡(luò)通信是指 通過計算機網(wǎng)絡(luò)進(jìn)行信息傳輸?shù)倪^程 ,包括數(shù)據(jù)傳輸、語音通話、視頻會議等。在網(wǎng)絡(luò)通信中,數(shù)據(jù)被分成一系列的數(shù)據(jù)包,并通過網(wǎng)絡(luò)傳輸?shù)侥康牡?。在?shù)據(jù)傳輸過程中,需要確保數(shù)據(jù)的完整性、準(zhǔn)確性和安全性。常見的網(wǎng)絡(luò)通信協(xié)議有T

    2024年02月10日
    瀏覽(33)
  • SCTP, TCP, UDP, IP, ICMP都在哪一層?(TCP/IP網(wǎng)絡(luò)通信協(xié)議學(xué)習(xí))

    SCTP, TCP, UDP, IP, ICMP都在哪一層?(TCP/IP網(wǎng)絡(luò)通信協(xié)議學(xué)習(xí))

    TCP/IP網(wǎng)絡(luò)通信協(xié)議最早是由 羅伯特·卡恩 (Robert E. Kahn)和 文頓·瑟夫 (Vinton G. Cerf)于1972年提出的,它是一個實際的協(xié)議棧。 OSI七層網(wǎng)絡(luò)通信協(xié)議最早是 由國際標(biāo)準(zhǔn)化組織 (ISO)于1977年提出的,它是一個理論模型。TCP/IP網(wǎng)絡(luò)通信協(xié)議由于其簡單性和實用性,成為 事實上

    2024年01月22日
    瀏覽(171)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包