在线不卡日本ⅴ一区v二区_精品一区二区中文字幕_天堂v在线视频_亚洲五月天婷婷中文网站

  • <menu id="lky3g"></menu>
  • <style id="lky3g"></style>
    <pre id="lky3g"><tt id="lky3g"></tt></pre>

    《網(wǎng)絡(luò)是怎么連接的》讀書筆記 – Tcp/IP連接

    《網(wǎng)絡(luò)是怎么連接的》讀書筆記 - Tcp/IP連接

    TCP和IP協(xié)議承載了整個(gè)互聯(lián)網(wǎng)的生命線,這一章算是本書核心部分,掌握這兩個(gè)協(xié)議也是學(xué)好網(wǎng)絡(luò)編程的基礎(chǔ)。

    Socket連接

    套接字鏈接在表面上看就是建立連接,交換數(shù)據(jù),斷開連接,雖然實(shí)際上細(xì)節(jié)肯定沒(méi)有那么簡(jiǎn)單,但是大體上的思路基本不變。

    協(xié)議棧建立連接

    這里記住一個(gè)前提:向操作系統(tǒng)內(nèi)部的協(xié)議棧發(fā)出委托時(shí),需要按照指定的順序來(lái)調(diào)用 Socket 庫(kù)中的程序組件。

    建立Socket的協(xié)議大部分情況都是Tcp/ip協(xié)議,Socket收發(fā)數(shù)據(jù)類似在兩個(gè)主機(jī)之間建立一個(gè)無(wú)形的管道,Socket建立的關(guān)鍵是要按照指定順序調(diào)用Socket程序組件,大致的構(gòu)建順序如下:

  • 創(chuàng)建Socket(Socket類似管道兩邊的出入口)
  • 綁定客戶端的套接字到服務(wù)端(類似接管道)
  • 交換數(shù)據(jù)。
  • 斷開Socket連接,解除綁定。
  • 轉(zhuǎn)化為具體的流程圖如下:

    創(chuàng)建Socket

    過(guò)程大致為應(yīng)用程序會(huì)把控制流程會(huì)轉(zhuǎn)移到 socket 內(nèi)部并執(zhí)行創(chuàng)建套接字的操作,完成之后控制流程又會(huì)被移交回應(yīng)用程序。

    創(chuàng)建完套接字之后,協(xié)議棧需要返回標(biāo)識(shí)符號(hào)也就是描述符用于標(biāo)識(shí)是哪一個(gè)套接字在進(jìn)行傳數(shù)據(jù),因?yàn)槲覀兛赡艽蜷_很多套接字連接訪問(wèn)不同的網(wǎng)站,具體的效果是我們?yōu)g覽器會(huì)打開很多個(gè)頁(yè)面,這時(shí)候每一個(gè)頁(yè)面都可能需要?jiǎng)?chuàng)建套接字,此時(shí)就需要識(shí)別和區(qū)分這些套接字依賴描述符。

    綁定客戶端的套接字到服務(wù)端

    連接操作核心是調(diào)用Socket的connect連接方法,此方法需要指定描述符、 服務(wù)器 IP 地址和端口號(hào)這 3 個(gè)參數(shù)。

    connect看上去挺復(fù)雜,其實(shí)本質(zhì)上就是完成連接動(dòng)作而已,連接成功會(huì)把IP地址和端口號(hào)記錄到套接字上面。

    描述符在創(chuàng)建Socket的時(shí)候已經(jīng)拿到了,IP地址則是在DNS解析的步驟完成,拿到IP之后會(huì)放入到應(yīng)用程序的某個(gè)位置替換保存,而端口號(hào)則是需要應(yīng)用程序事先提供。

    端口可以簡(jiǎn)單看作應(yīng)用程序的入口,DNS解析的IP只能知道主機(jī)在哪但是本身發(fā)往哪個(gè)應(yīng)用程序是不清楚的,我們可以想象DNS解析類似地圖上告訴我們高速的收費(fèi)站坐標(biāo),但是他并不知道對(duì)應(yīng)數(shù)據(jù)送往那個(gè)閘口)。

    這里可以理解為端口就是收費(fèi)站過(guò)站口,計(jì)算機(jī)會(huì)要求程序?qū)Υ龖?yīng)用程序預(yù)設(shè)明確的端口參與網(wǎng)絡(luò)交互。

    傳遞消息

    接下來(lái)的操作是調(diào)用read和write函數(shù)完成消息傳遞動(dòng)作,這一步就是底層的流讀寫操作。

    斷開連接

    這一步需要簡(jiǎn)單理解為需要一方主動(dòng)發(fā)起斷開申請(qǐng)瀏覽器調(diào)用read收發(fā)數(shù)據(jù)同時(shí)會(huì)收到關(guān)閉請(qǐng)求,此時(shí)客戶端確認(rèn)請(qǐng)求之后將會(huì)停止請(qǐng)求并且開始釋放Socket連接。

    為什么不能用描述符標(biāo)識(shí)應(yīng)用程序的入口?

    描述符是和委托創(chuàng)建套接字的 應(yīng)用程序進(jìn)行交互時(shí)使用的,并不是用來(lái)告訴網(wǎng)絡(luò)連接的另一方。

    客戶端也無(wú)法知道服務(wù)器上的描述符,客戶端也無(wú)法通過(guò)服務(wù)器端的描述符去確定位于服務(wù)器上的某 一個(gè)套接字?!?/p>

    Socket連接中大致介紹了協(xié)議棧是如何通過(guò)網(wǎng)卡完成和目標(biāo)服務(wù)器的連接、斷開、收發(fā)數(shù)據(jù)的過(guò)程下面按照順序講述各個(gè)步驟的細(xì)節(jié)。

    下面我們根據(jù)上面所講的各個(gè)步驟按順序進(jìn)行詳細(xì)介紹。

    創(chuàng)建套接字

    首先來(lái)看一下創(chuàng)建套接字的情況,下面是協(xié)議棧的內(nèi)容。

    委托分發(fā)被拆分為好幾個(gè)部分,最上面可以看作瀏覽器,協(xié)議棧中主要有兩張協(xié)議 TCP和UDP, TCP主要是用于和服務(wù)器交互收發(fā)數(shù)據(jù)的,UDP則用于較短的控制數(shù)據(jù)。

    IP協(xié)議主要控制網(wǎng)絡(luò)收發(fā)操作,主要工作是把一個(gè)個(gè)拆分的網(wǎng)絡(luò)包發(fā)給通信的目標(biāo)對(duì)象,IP協(xié)議包括 ICMP和 ARP協(xié)議,前者告知傳輸過(guò)程的錯(cuò)誤和控制信息,后者傳遞以太網(wǎng)MAC地址。

    MAC 地址:符合 IEEE 規(guī)格的局域網(wǎng)設(shè)備都使用同一格式的地址,這種地址被稱為 MAC 地址

    驅(qū)動(dòng)部分是為了讓操作系統(tǒng)能正常使用硬件進(jìn)行網(wǎng)絡(luò)收發(fā)的一個(gè)“適配器”,而所有的電信號(hào)最終要通過(guò)網(wǎng)卡完成。

    套接字和協(xié)議棧

    協(xié)議棧實(shí)際上是根據(jù)套接字傳遞的信息來(lái)決定做什么操作的,比如發(fā)數(shù)據(jù)要看IP和端口號(hào)。

    以Windows的套接字為例,直接在CMD中使用 netstat操作即可:

    復(fù)制代碼 隱藏代碼C:UsersXander>netstat -ano 協(xié)議 本地地址 外部地址 狀態(tài) PID TCP 0.0.0.0:49666 0.0.0.0:0 LISTENING 604 TCP 0.0.0.0:49667 0.0.0.0:0 LISTENING 1892 TCP 0.0.0.0:49668 0.0.0.0:0 LISTENING 4508 TCP 0.0.0.0:57621 0.0.0.0:0 LISTENING 22748 TCP 127.0.0.1:1001 0.0.0.0:0 LISTENING 4 TCP 127.0.0.1:1043 127.0.0.1:1061 ESTABLISHED 8452 TCP 127.0.0.1:1043 127.0.0.1:1063 ESTABLISHED 8452 UDP 192.168.159.1:1900 *:* 3060 UDP 192.168.159.1:5353 *:* 5248 UDP 192.168.159.1:58085 *:* 3060

    netstat 命令 的 ano 三個(gè)參數(shù)主要用于擴(kuò)展IP地址端口以及PID的顯示,以及一些隱式的可能存在的通信也會(huì)被記錄。

    LISTENING:表示等待對(duì)方連接ESTABLISHED :表示完成連接并且進(jìn)行數(shù)據(jù)通信操作

    套接字和協(xié)議棧和應(yīng)用程序的交互流程如下:

  • 協(xié)議棧在操作套接字之前,需要事先開辟一塊空間來(lái)存放用于操作套接字的必要信息。
  • 協(xié)議棧需要向應(yīng)用程序返回描述符表示當(dāng)前連接的是哪一個(gè)“管道”。
  • 之后應(yīng)用程序需要和協(xié)議棧交互就必須要攜帶描述符,不過(guò)這樣也節(jié)省了協(xié)議棧了解應(yīng)用程序要和哪一個(gè)套接字交互。
  • 連接服務(wù)器

    連接的目的是為了讓兩臺(tái)不在同一個(gè)地方的主機(jī)能夠相互認(rèn)識(shí)對(duì)方,這時(shí)候不可避免地需要互相提供自己的信息,這樣才能正確的建立連接然后使用套接字傳輸數(shù)據(jù)。

    連接的含義

    人和人之間的溝通有時(shí)候可以不使用一個(gè)語(yǔ)言,只要雙方都聽懂就行,但是對(duì)于計(jì)算機(jī)是行不通的。

    所以連接操作的控制信息要根據(jù)通信規(guī)則確定,協(xié)議棧在通信之前需要依靠一塊空間來(lái)存放必要數(shù)據(jù),這塊內(nèi)存空間稱為緩沖區(qū)。

    連接需要雙方各自告知自己的信息,所以連接最開始的時(shí)候是沒(méi)有任何數(shù)據(jù)交互的,由于是TCP是全雙工的協(xié)議客戶端和服務(wù)器都需要建立套接字,不過(guò)雙方不知道和誰(shuí)連接,所以需要在客戶端和服務(wù)端各自開辟一塊空間來(lái)存放對(duì)方的IP和端口等必要的傳輸信息。

    為了讓雙方既可以正常通信,又可以根據(jù)自己的系統(tǒng)設(shè)計(jì)協(xié)議棧和套接字的控制信息處理方式,網(wǎng)絡(luò)通信設(shè)計(jì)采用了 控制信息的方式讓不同的計(jì)算機(jī)和系統(tǒng)能相互認(rèn)識(shí)。

    所謂的控制信息可以認(rèn)為是一種 通用語(yǔ)言,只要是符合這個(gè)控制信息規(guī)范的頭部信息就可以被其他的計(jì)算機(jī)認(rèn)識(shí)。

    控制信息分為兩類:

  • 客戶端和服務(wù)器的交換的控制信息,主要用于整個(gè)通信過(guò)程,這些內(nèi)容在TCP協(xié)議進(jìn)行規(guī)定。生活的例子理解是我們和別人通話之前,兩邊都得知道對(duì)方的電話號(hào)碼和基本身份。
  • 保存在套接字中用來(lái)控制協(xié)議棧操作的信息,這些信息主要用來(lái)傳輸數(shù)據(jù),通常需要包括控制信息和數(shù)據(jù)塊,套接字需要通過(guò)控制信息了解到發(fā)來(lái)的是什么類型的數(shù)據(jù),然后協(xié)議棧才能配合處理數(shù)據(jù)。
  • 由于在一開始傳輸?shù)臅r(shí)候是沒(méi)有具體數(shù)據(jù)的,通常是一個(gè)空的報(bào)文頭,所以這個(gè)控制信息也被叫做 協(xié)議頭部, 比如下面提到的TCP頭部,IP頭部。

    第一類:TCP 頭部格式

    第二類:套接字中的信息

    連接的實(shí)際操作

    連接的實(shí)際操作主要是調(diào)用CONNECT函數(shù),協(xié)議首先會(huì)傳遞給TCP模塊,通過(guò)TCP模塊交換獲取控制信息的頭部,以此了解具體要連接的套接字信息,然后把頭部的SYN比特設(shè)置為1,表示可以連接。

    TCP 模塊處創(chuàng)建表示連接控制信息的頭部,接著便把信息傳遞給IP模塊進(jìn)行委托發(fā)送。

    三次握手

    交換頭部信息之后,接著便是常見的TCP三次握手的過(guò)程:

    • 第一步:客戶端主動(dòng)打開TCB端口,服務(wù)器被動(dòng)打開TCB端口。發(fā)起方攜帶一個(gè)SYN標(biāo)志,并且攜帶一個(gè)ISN序號(hào)Seq=x,但是需要注意的是第一步的過(guò)程這個(gè)ISN序號(hào)是隱藏傳遞的(因?yàn)闆](méi)有傳遞數(shù)據(jù)),因?yàn)槿绻?qǐng)求不存在數(shù)據(jù)的交換則不會(huì)被顯示??蛻舳税l(fā)送SYN命令之后進(jìn)入設(shè)置SYN=1,并且設(shè)置SYN-SENT(同步-已發(fā)送狀態(tài))。
    • 第二步:服務(wù)器收到客戶端TCP報(bào)文之后,也將SYN=1,并且回送一個(gè)新的ISN序號(hào)ack=x+1,并且將ACK=1表示自己收到了,然后在返回參數(shù)回送自己新的序列號(hào)表示自己的確認(rèn)請(qǐng)求Seq=y,將狀態(tài)設(shè)置為SYN-RCVD(同步收到)狀態(tài),(表示希望收到的序號(hào)為xxxx1522),最后也是指定MSS。
    • 第三步:客戶端收到服務(wù)器的確認(rèn)報(bào)文之后,還需要向服務(wù)端返回確認(rèn)報(bào)文,確認(rèn)報(bào)文的ACK=1,并且回傳服務(wù)器傳遞的ISN序號(hào)+1(ack = y+1),以及自己的ISN序號(hào)+1(Seq = x+1),此時(shí)TCP連接進(jìn)入已連接狀態(tài),ACK是可以攜帶數(shù)據(jù)的,但是如果不攜帶數(shù)據(jù)則不消耗序列號(hào)。
    • 最后一步:當(dāng)服務(wù)器收到客戶端的確認(rèn),也進(jìn)入已連接狀態(tài)。

    經(jīng)過(guò)三次握手連接建立,直到斷開連接之前都可以傳遞數(shù)據(jù)。

    收發(fā)數(shù)據(jù)

    收發(fā)數(shù)據(jù)有兩個(gè)重點(diǎn):

    • 第一點(diǎn)是收發(fā)數(shù)據(jù)并不關(guān)心數(shù)據(jù)的格式,而是根據(jù)頭部信息來(lái)辨別是什么類型的數(shù)據(jù),對(duì)于協(xié)議棧來(lái)說(shuō)接收的的內(nèi)容都是二進(jìn)制的數(shù)據(jù)。
    • 第二點(diǎn)是利用緩沖區(qū)減少頻繁的數(shù)據(jù)傳輸提高傳輸效率。

    緩沖區(qū)的大小如何控制?

    • 每個(gè)數(shù)據(jù)包的數(shù)據(jù)長(zhǎng)度,協(xié)議棧會(huì)根據(jù)一個(gè)叫作 MTU的參數(shù)來(lái)進(jìn)行判斷,但是MTU指的是總長(zhǎng)度,除開頭部信息之后獲得真實(shí)的數(shù)據(jù)長(zhǎng)度MSS。
    • 時(shí)間,這個(gè)時(shí)間指的是固定的時(shí)間內(nèi)容不管緩沖區(qū)有有沒(méi)有達(dá)到MSS長(zhǎng)度必須發(fā)送數(shù)據(jù)的時(shí)間,目的是防止等待時(shí)間過(guò)長(zhǎng)造成請(qǐng)求延遲。

    名詞解釋:

    MTU:一個(gè)網(wǎng)絡(luò)包的最大長(zhǎng)度,以太網(wǎng)中一般為 1500 字節(jié)。MSS:除去頭部之后,一個(gè)網(wǎng)絡(luò)包所能容納的 TCP 數(shù)據(jù)的最大長(zhǎng)度。

    但這兩個(gè)因素實(shí)際上并不能完全決定收發(fā)數(shù)據(jù)的效率平衡,TCP協(xié)議沒(méi)有規(guī)定協(xié)議棧如何平衡,具體需要看操作系統(tǒng)如何決定。

    實(shí)際上協(xié)議棧收發(fā)數(shù)據(jù)是有所保留的,并不是強(qiáng)制按照協(xié)議的規(guī)定處理,而是給了應(yīng)用程序一些可控選項(xiàng),比如瀏覽器這種要求實(shí)時(shí)性的應(yīng)用程序通常不使用緩沖區(qū)。Http請(qǐng)求拆分

    通常情況http的請(qǐng)求響應(yīng)內(nèi)容可以通過(guò)一個(gè)網(wǎng)絡(luò)包完成,但是針對(duì)POST請(qǐng)求等大表單的數(shù)據(jù)提交則通常會(huì)觸發(fā)TCP拆包操作。

    拆包是根據(jù)MSS的參數(shù)確定的,發(fā)送緩沖區(qū)會(huì)根據(jù)這個(gè)參數(shù)把一個(gè)超過(guò)一次請(qǐng)求長(zhǎng)度的數(shù)據(jù)拆分為多個(gè)包,但是因?yàn)閷?shí)際上同屬一份數(shù)據(jù),拆分之后所有的數(shù)據(jù)包都需要添加相同的頭部。

    注意:TCP是面向字節(jié)流的協(xié)議,就是沒(méi)有界限的一串?dāng)?shù)據(jù),本沒(méi)有“包”的概念,“粘包”和“拆包”一說(shuō)是為了有助于形象地理解這兩種現(xiàn)象。

    TCP粘包

    TCP除了拆包動(dòng)作之外還包含粘包的操作,所謂粘包是指TCP協(xié)議中發(fā)送方發(fā)送的若干包數(shù)據(jù)到接收方接收時(shí)粘成一個(gè)包,從接收緩沖區(qū)角度來(lái)看后一個(gè)數(shù)據(jù)的頭緊接著前一包數(shù)據(jù)的尾部。

    解決粘包、拆包問(wèn)題策略?

    粘包和拆包需要解決容易造成半包讀寫的根本問(wèn)題,解決辦法也有很多種,主要的策略基本很多網(wǎng)上資料都有講到,這里直接搬運(yùn)結(jié)論了:

    • 請(qǐng)求消息定長(zhǎng),如果緩沖區(qū)不滿,則通過(guò)補(bǔ)0的方式達(dá)到長(zhǎng)度,防止粘包和拆包。
    • 在包尾增加回車換行符進(jìn)行分割,例如FTP協(xié)議;
    • 將消息分為頭部和消息體,頭部中保存整個(gè)消息的長(zhǎng)度,只有讀取到足夠長(zhǎng)度的消息之后才算是讀到了一個(gè)完整的消息;
    • 通過(guò)自定義協(xié)議進(jìn)行粘包和拆包的處理。(幾乎不用)

    ACK號(hào)確認(rèn)網(wǎng)絡(luò)包收發(fā)

    ACK號(hào)碼除了在三次握手的過(guò)程中確認(rèn)對(duì)方是否有收到請(qǐng)求之外,還能作為判斷接收的數(shù)據(jù)包是否完整的依據(jù),在進(jìn)行數(shù)據(jù)傳輸?shù)臅r(shí)候,接收方會(huì)將到目前為止接收到的數(shù)據(jù)長(zhǎng)度加起來(lái),計(jì)算出一共已經(jīng)收到了多少個(gè)字節(jié),然后將這個(gè)數(shù)值寫入 TCP頭部的 ACK 號(hào)中發(fā)送給發(fā)送方,以表示自己到底受到了多少數(shù)據(jù),如果中間存在缺少數(shù)據(jù)則服務(wù)端重新傳輸即可。

    當(dāng)然僅靠ACK號(hào)不能完全作為參考依據(jù),并且只使用ACK號(hào)是只考慮 單向傳輸?shù)那闆r,但是TCP是全雙工協(xié)議,無(wú)法確定數(shù)據(jù)接收方來(lái)自哪一方。

    解決這個(gè)問(wèn)題也很簡(jiǎn)單,實(shí)際在進(jìn)行雙向數(shù)據(jù)傳輸?shù)臅r(shí)候雙方各自會(huì)額外計(jì)算一個(gè)序號(hào),序號(hào)其實(shí)就是一組隨機(jī)數(shù),在接收方收到數(shù)據(jù)之后每次都需要把序號(hào)+1回傳給發(fā)送方表示自己接收到哪一個(gè)序號(hào)之前的所有數(shù)據(jù)。

    通過(guò)ACK+序號(hào)的方式確保數(shù)據(jù)正確傳輸,這樣可以使得其他網(wǎng)絡(luò)通信組件不需要額外的失敗補(bǔ)償機(jī)制,如果發(fā)現(xiàn)丟包或者數(shù)據(jù)不完整的情況,直接根據(jù)序號(hào)進(jìn)行重傳重發(fā)的操作即可。

    影響數(shù)據(jù)傳輸?shù)囊蛩?/p>

    主要影響因素是返回ACK號(hào)的等待時(shí)間。

    如果ACK號(hào)遲遲沒(méi)有響應(yīng)給對(duì)方服務(wù)器,勢(shì)必會(huì)影響整個(gè)網(wǎng)絡(luò)傳輸?shù)男?,如果下一個(gè)數(shù)據(jù)已經(jīng)準(zhǔn)備好上一個(gè)返回包卻沒(méi)有發(fā)回去,很容易造成網(wǎng)絡(luò)的堵塞,對(duì)方遲遲拿不到正確結(jié)果。

    網(wǎng)絡(luò)環(huán)境的復(fù)雜多變,這個(gè)等待時(shí)間不可能是固定的,所以TCP使用了動(dòng)態(tài)時(shí)間的方法進(jìn)行調(diào)整,具體的調(diào)整方法就是使用滑動(dòng)窗口。

    滑動(dòng)窗口

    滑動(dòng)窗口:指的是在不等待ACK返回結(jié)果的情況下直接雙方互相不間斷的發(fā)送數(shù)據(jù)。

    雙方需要通過(guò)各自的緩沖區(qū)順序返回ACK信息,但是如果無(wú)限制的發(fā)送數(shù)據(jù)會(huì)導(dǎo)致數(shù)據(jù)無(wú)法處理出現(xiàn)丟包,所以滑動(dòng)窗口的關(guān)鍵是接收方需要告訴發(fā)送方自己最多能接收多少數(shù)據(jù)。

    滑動(dòng)窗口的細(xì)節(jié)通過(guò)一張圖更好理解:

    關(guān)于接收方的接收量,最大能承受處理多少數(shù)據(jù)是通過(guò)緩沖區(qū)大小確定的。另外需要注意下面的圖只有單向的部分,實(shí)際上對(duì)于雙向來(lái)說(shuō)都是類似的處理。

    影響數(shù)據(jù)傳輸?shù)拇我蛩兀悍祷?ACK號(hào)和更新窗口的時(shí)機(jī)。

    關(guān)于這一點(diǎn)直接記住一個(gè)結(jié)論,接收方在發(fā)送 ACK 號(hào)和窗口更新時(shí),并不會(huì)馬上把包發(fā)送出去,而是會(huì)等待一段時(shí)間,等到其他的通知合并到一起處理,因?yàn)锳CK號(hào)體現(xiàn)的是已經(jīng)收到的包的數(shù)據(jù)量,使用這樣延遲發(fā)送的方式也可以防止過(guò)多的更新數(shù)據(jù)包出現(xiàn)。

    最終協(xié)議棧收發(fā)數(shù)據(jù)的細(xì)節(jié)如下:

  • 協(xié)議棧會(huì)根據(jù)收到的數(shù)據(jù)塊和TCP或者IP頭部解析內(nèi)容,如果確認(rèn)收到數(shù)據(jù)則返回ACK + 序號(hào)。
  • 協(xié)議棧會(huì)把數(shù)據(jù)塊放到緩沖區(qū)進(jìn)行存儲(chǔ),利用滑動(dòng)窗口的特性按照順序處理數(shù)據(jù)交給應(yīng)用程序處理。
  • 協(xié)議棧會(huì)將接收到的數(shù)據(jù)復(fù)制到應(yīng)用程序指定的內(nèi)存地址中,然后將控制流程交回應(yīng)用程序
  • 斷開連接

    斷開連接的部分包含斷開連接和刪除套接字的操作,斷開連接也就是經(jīng)典的四次揮手的操作,而刪除套接字則需要注意在協(xié)議棧中并沒(méi)有規(guī)定關(guān)閉的時(shí)間,但是通常情況下過(guò)幾分鐘之后會(huì)刪除套接字。

    四次揮手端口tcp連接

    • 第一步(客戶端):TCP發(fā)送釋放連接的報(bào)文,停止發(fā)送數(shù)據(jù),釋放報(bào)文首部,把FIN=1,同時(shí)發(fā)送序列號(hào),根據(jù)上一次傳送的序列號(hào)+1傳送Seq = t + 1(由于下圖是在連接之后立馬進(jìn)行四次揮手,所以序列號(hào)沒(méi)有變),此時(shí)客戶端進(jìn)行終止等待1的狀態(tài)。注意FIN不攜帶數(shù)據(jù)也需要消耗序列號(hào)。
    • 第二步(服務(wù)端):服務(wù)器回送確認(rèn)報(bào)文,發(fā)出確認(rèn)報(bào)文,ACK=1,并且把回傳序列號(hào)+1回傳(ack = t + 1),然后再帶上自己的序列號(hào)Seq = y,此時(shí)服務(wù)端進(jìn)入CLOSE-WAIT狀態(tài)(關(guān)閉等待狀態(tài)),TCP服務(wù)器此時(shí)需要停止上層應(yīng)用客戶端向服務(wù)端請(qǐng)求釋放,處于 半關(guān)閉 階段,此時(shí)服務(wù)端依然可以向客戶端發(fā)數(shù)據(jù)并且客戶端需要接收并處理,關(guān)閉等待狀態(tài)意味著整個(gè)狀態(tài)還需要持續(xù)一段時(shí)間。
    • 第三步(客戶端):客戶端接收到服務(wù)端確認(rèn)請(qǐng)求,此時(shí)客戶端進(jìn)入到FIN-WAIT-2終止等待2的階段,等待服務(wù)器的釋放報(bào)文。(還有一部分服務(wù)器沒(méi)有發(fā)送完的數(shù)據(jù)需要處理)
    • 第四步(服務(wù)端):服務(wù)器把最后的數(shù)據(jù)處理完畢,向客戶端發(fā)送釋放報(bào)文,F(xiàn)IN=1,ack=t + 1,由于需要把剩下的數(shù)據(jù)發(fā)送完成,假設(shè)處理完成之后需要帶上自己的序列號(hào)Seq=w,服務(wù)器進(jìn)入最后確認(rèn)狀態(tài),等待客戶端確認(rèn)。
    • 第五步(客戶端):客戶端收到報(bào)文之后,發(fā)出確認(rèn) ACK=1,ack=w+1,自己的序列號(hào)為Seq = t + 1,此時(shí)客戶端進(jìn)入到了TIME-WAIT(時(shí)間等待狀態(tài)),此時(shí)客戶端還是沒(méi)有釋放,必須經(jīng)過(guò)**2 * MSL(最長(zhǎng)報(bào)文壽命)**之后,客戶端撤掉TCB之后才進(jìn)入CLOSED狀態(tài)。
    • 第六步(服務(wù)端):服務(wù)器收到客戶端的請(qǐng)求立馬進(jìn)入CLOSE狀態(tài),同時(shí)撤銷TCB,結(jié)束此次TCP的連接。(服務(wù)端結(jié)束TCP連接要比客戶端早一些)

    套接字和協(xié)議棧和對(duì)方服務(wù)器的交互流程細(xì)節(jié)還是比較多的,這里可以發(fā)現(xiàn)實(shí)際上三次握手和四次揮手實(shí)際上只是網(wǎng)絡(luò)連接當(dāng)中很小的一部分,最后是從連接服務(wù)到數(shù)據(jù)收發(fā)到斷開連接的一張簡(jiǎn)單總結(jié)圖,建議當(dāng)作一個(gè)大概的流程參考:

    IP和以太網(wǎng)的收發(fā)操作

    上面的部分比較貼近TCP協(xié)議的相關(guān)操作,TCP完成連接收發(fā)的同時(shí)其實(shí)都需要IP模塊的配合,在了解這兩個(gè)模塊如何配合工作之前需要了解完整的網(wǎng)絡(luò)包是如何組成的。

    包的組成

    對(duì)于任何一個(gè)網(wǎng)絡(luò)包,都有最外層的抽象概念,那就是頭部和數(shù)據(jù) 兩個(gè)部分

    上面的部分有一個(gè)這樣的圖,里面套接字中的TCP數(shù)據(jù),這里需要注意在TCP控制信息的前面就是以太網(wǎng)和IP的控制信息,對(duì)于只傳輸控制信息的網(wǎng)絡(luò)包雖然沒(méi)有數(shù)據(jù)的部分,但是可以把協(xié)議的頭部信息作為數(shù)據(jù)部分。

    通過(guò)下面的圖也可以發(fā)現(xiàn),所有的網(wǎng)絡(luò)包必須要委托以太網(wǎng)和IP控制信息才能完成傳輸。

    把存放數(shù)據(jù)的網(wǎng)絡(luò)包進(jìn)行拆分,可以看到下面的TCP/IP 包結(jié)構(gòu):

    我們可以簡(jiǎn)單把頭部和數(shù)據(jù)看做是平時(shí)的快遞,頭部是面單,指示從哪里到哪里,然后這個(gè)“快遞”會(huì)通過(guò)網(wǎng)絡(luò)轉(zhuǎn)發(fā)設(shè)備的查表操作判斷傳輸?shù)侥莻€(gè)方向。

    轉(zhuǎn)發(fā)設(shè)備是什么?這里建議看看第一章的關(guān)于認(rèn)識(shí)網(wǎng)絡(luò)傳輸?shù)幕靖拍?,這里簡(jiǎn)單提一下:

    • 路由器根據(jù)目標(biāo)地址判斷下一個(gè)路由器的位置
    • 集線器在子網(wǎng)中將網(wǎng)絡(luò)包傳輸?shù)较乱粋€(gè)路由

    但是實(shí)際上集線器和路由器各自有不同分工,集線器負(fù)責(zé)管理以太網(wǎng)規(guī)則傳輸包設(shè)備,路由器管理IP轉(zhuǎn)發(fā)規(guī)則,所以上面兩個(gè)步驟也可以做下面的理解:

    • IP協(xié)議根據(jù)層級(jí)規(guī)則判斷下一個(gè)IP轉(zhuǎn)發(fā)設(shè)備。
    • 子網(wǎng)的以太網(wǎng)協(xié)議轉(zhuǎn)發(fā)給下一個(gè)轉(zhuǎn)發(fā)設(shè)備。

    實(shí)際上頭部部分應(yīng)該分為 MAC 頭部 和 IP頭部。為什么要把頭部拆分為兩個(gè)協(xié)議?實(shí)際上是為了讓協(xié)議之間可以實(shí)現(xiàn)替換,比如MAC可以替換為局域網(wǎng)、ADSL、FTTH。同時(shí)因?yàn)榛ヂ?lián)網(wǎng)這樣龐大的網(wǎng)絡(luò)架構(gòu),需要更加細(xì)化的分工。

    小結(jié)

    實(shí)際上網(wǎng)絡(luò)包的封裝應(yīng)該范圍三個(gè)部分:

    第一部分是TCP模塊組織頭部信息和數(shù)據(jù)包(當(dāng)然也可能沒(méi)有數(shù)據(jù)只有控制信息)。

    第二部分是把整個(gè)TCP模塊塞到IP模塊的后面,然后經(jīng)過(guò)網(wǎng)卡發(fā)送出去。

    第三部分是在IP模塊前面加上Mac信息。

    關(guān)鍵:無(wú)論要收發(fā)的包是控制包還是數(shù)據(jù)包,IP 對(duì)各種類型的包的收發(fā)操作都是相同的。

    名詞解釋ADSL:可以理解為以前寬帶使用撥號(hào)連接互聯(lián)網(wǎng)上網(wǎng)的方式。

    非對(duì)稱數(shù)字用戶線路(英語(yǔ):Asymmetric Digital Subscriber Line)又稱非對(duì)稱數(shù)字用戶環(huán)路(Asymmetric Digital Subscriber Loop),簡(jiǎn)稱ADSL。ADSL是一個(gè)依靠銅質(zhì)電話線的數(shù)據(jù)傳輸技術(shù)比傳統(tǒng)的調(diào)制器更快。

    FTTH:其實(shí)就是現(xiàn)在的光纖通信。

    光纖到戶(英語(yǔ):Fiber To The Home,縮寫:FTTH)是一種光纖通信的傳輸方法。是直接把光纖接到用戶的家中(用戶所需的地方)。

    這種光纖通信方式及策略與FTTN、FTTC、HFC(Hybrid Fiber Coaxial)等也不同,它們都是需要依賴傳統(tǒng)的金屬電線,包括雙絞線及同軸電纜等,作“最后一哩”的信息傳輸。

    IP 協(xié)議頭部

    IP類似快遞上的單號(hào),所以實(shí)際上IP模塊是無(wú)法決定自己選擇正確的地址了,哪怕應(yīng)用程序通過(guò)TCP告訴IP發(fā)的地址式是一個(gè)錯(cuò)誤地址,IP也無(wú)法自行修正只能照做。

    從這樣的特點(diǎn)可以看出IP頭部又有點(diǎn)類似快遞員,和網(wǎng)上買東西商家發(fā)錯(cuò)地址或者我們填錯(cuò)地址一樣,不能把責(zé)任賴在快遞員上。

    IP協(xié)議頭部的組成類似下面的結(jié)構(gòu),注意IP地址的長(zhǎng)度固定需要32Bit的空間占用。

    這里需要注意“發(fā)送方的IP”地址不是指計(jì)算機(jī)的IP,而是指網(wǎng)卡對(duì)應(yīng)的IP,因?yàn)镮P不是分配和計(jì)算機(jī)而是網(wǎng)卡的,當(dāng)一個(gè)計(jì)算機(jī)有多個(gè)網(wǎng)卡就會(huì)存在多個(gè)IP。

    那么應(yīng)該如何判斷包發(fā)送給哪一個(gè)網(wǎng)卡?這里涉及到IP協(xié)議規(guī)則,無(wú)論是路由器的轉(zhuǎn)發(fā)還是協(xié)議棧的處理都需要按照IP協(xié)議轉(zhuǎn)給下一個(gè)用戶。

    查詢分配給哪一個(gè)網(wǎng)卡在不同操作系統(tǒng)中的查詢方式不同,查詢發(fā)送端需要查詢是哪個(gè)網(wǎng)卡把包發(fā)給了路由器,這個(gè)動(dòng)作只需要簡(jiǎn)單的根據(jù)路由器IP地址和網(wǎng)卡的IP進(jìn)行比對(duì)。

    在windows中可以通過(guò)命令route print查看路由信息。

    獲取IP和網(wǎng)卡之后,還需要知道包所屬的協(xié)議,委托內(nèi)容是固定的,比如TCP模塊就是06,UDP就是17,大部分請(qǐng)求都是HTTP,使用TCP的方式傳輸。

    以太網(wǎng)Mac頭部

    TCP/IP模塊只能在傳輸層上互相了解,但是往下的鏈路層以太網(wǎng)用同樣的規(guī)則是行不通的,所以頭部加上TCP/IP的頭部之后,還需要在頭部加上Mac頭部,Mac頭部包含了發(fā)送方和接收方的Mac信息,這里可以簡(jiǎn)單理解為Mac和IP的作用類似,不過(guò)Mac頭部是48Bit,而IP頭部是32Bit。

    需要注意以太類型就是Mac包裝的后面的真實(shí)數(shù)據(jù)的類型, 如果是IP就是IP協(xié)議。另外需要注意在發(fā)送Mac包給接收方之前,由于不知道對(duì)方的Mac地址,所以還需要一步查詢操作。

    注意IP 模塊根據(jù)路由表 Gateway 欄的內(nèi)容判斷應(yīng)該把包發(fā)送給誰(shuí)。

    下面是Mac頭部的組成:

    查詢Mac地址

    查詢對(duì)方的Mac地址需要用到ARP( Address Resolution Protocol,地址解析協(xié)議),ARP通過(guò)廣播的方法查找到目標(biāo)地址,所謂廣播就是字面意思把消息發(fā)給所有的其他互聯(lián)網(wǎng)用戶,等待對(duì)方應(yīng)答。

    為了防止每次查詢都要帶ARP的數(shù)據(jù),所以有一塊ARP的緩存專門緩存這個(gè)地址,但是需要注意這個(gè)緩存和IP模塊的IP地址一樣,過(guò)一段時(shí)間會(huì)被ARP緩存淘汰掉,但是如果IP剛剛變化可能會(huì)導(dǎo)致ARP緩存未及時(shí)更新導(dǎo)致網(wǎng)絡(luò)異常。

    實(shí)際整個(gè)工作都是由IP模塊完成的,雖然Mac地址是以太網(wǎng)數(shù)據(jù)傳輸?shù)谋匾獌?nèi)容,但是實(shí)際上讓IP模塊負(fù)責(zé)這些工作是有利的。

    為什么需要以太網(wǎng)?

    # 有了 IP 地址,為什么還要用 MAC 地址?

    以太網(wǎng)基本知識(shí)

    首先來(lái)看看以太網(wǎng)的基本發(fā)展,雖然設(shè)計(jì)結(jié)構(gòu)越來(lái)越精細(xì),但是本質(zhì)上干的活卻沒(méi)有發(fā)生變化。

    以太網(wǎng)早期原型本質(zhì)上可以看作是一根網(wǎng)線以及一個(gè)用于收發(fā)的設(shè)備,網(wǎng)絡(luò)信號(hào)發(fā)送之后通過(guò)廣播最終到達(dá)所有設(shè)備,在開頭的收發(fā)信息讓其他人可以知道信息最終要發(fā)給誰(shuí),在Mac頭部就包含了“收貨地址”,而具體發(fā)送了什么類型的可以通過(guò)上面的“以太類型”進(jìn)行判斷。

    以太網(wǎng)在后續(xù)的發(fā)展中將主干網(wǎng)線替 換成了一個(gè)中繼式集線器,收發(fā)器變成雙絞線,雖然形式變了,但是本質(zhì)的工作沒(méi)有變。

    以太網(wǎng)到了現(xiàn)代最終由交換式集線器完成所有的操作,并且網(wǎng)絡(luò)請(qǐng)求只有請(qǐng)求方和接收方可以互通,集成度增加以及網(wǎng)絡(luò)傳輸安全性能增加。

    但是以太網(wǎng)無(wú)論怎么發(fā)展性質(zhì)始終沒(méi)有任何變動(dòng):

    MAC 地址代表的目的地,用發(fā)送方 MAC 地址識(shí)別發(fā)送方,用以太類型識(shí)別包的內(nèi)容。

    IP模塊轉(zhuǎn)光(或電)信號(hào)

    網(wǎng)絡(luò)信號(hào)發(fā)送依賴網(wǎng)卡,但是網(wǎng)卡并不是插上電就可以使用的,還需要依賴初始化以及驅(qū)動(dòng)程序才能完成操作,驅(qū)動(dòng)程序和初始化操作在其他很多電腦硬件中比較常見,但是以太網(wǎng)有比較獨(dú)特的驅(qū)動(dòng)操作,那就是控制以太網(wǎng)收發(fā)操作的MAC當(dāng)中收發(fā)MAC地址。

    另外網(wǎng)卡還有一個(gè)特性是網(wǎng)卡的 ROM 中保存著全世界唯一的 MAC 地址,這是在生產(chǎn)網(wǎng)卡的時(shí)候就已經(jīng)決定。

    所以可以看到最終完成IP數(shù)據(jù)轉(zhuǎn)化的關(guān)鍵是驅(qū)動(dòng)程序,網(wǎng)卡中保存的 MAC 地址會(huì)依賴網(wǎng)卡驅(qū)動(dòng)程序讀取并分配給 MAC模塊。

    網(wǎng)絡(luò)包的控制信息

    MAC模塊工作在網(wǎng)卡調(diào)用MAC包發(fā)送請(qǐng)求命令之后,MAC模塊的工作是劃分網(wǎng)絡(luò)包的“邊界”。

    為了劃分邊界,MAC模塊會(huì)加上三個(gè)控制信息:

  • 報(bào)頭:是一串像 10101010…這樣 1 和 0 交替出現(xiàn)的比特序列,長(zhǎng)度為** 56 比特**,它的作用是確定包的讀取時(shí)機(jī)。
  • 起始幀分界符(SFD):確定幀的起始位置,主要是輔助電信號(hào)切分報(bào)文頭部和真實(shí)的網(wǎng)絡(luò)包邊界,并且判斷出每個(gè)比特的界限。
  • FCS:檢查包傳輸過(guò)程中因噪聲導(dǎo)致的波形紊亂、數(shù)據(jù)錯(cuò)誤,它是一串 32 比特的序列,是通過(guò)一個(gè)公式對(duì)包中從頭到尾 的所有內(nèi)容進(jìn)行計(jì)算而得出來(lái)的
  • 響應(yīng)內(nèi)容傳輸從IP給TCP

    當(dāng)服務(wù)器接收到網(wǎng)絡(luò)包之后,首先協(xié)議棧會(huì)判斷以太網(wǎng)頭部的以太類型,發(fā)現(xiàn)是0800為TCP/IP協(xié)議,接下來(lái)是IP模塊工作,首先是檢查IP頭部是否正確,IP地址是否正確。

    如果接收方是window客戶端,因?yàn)椴粫?huì)對(duì)包進(jìn)行轉(zhuǎn)發(fā),如果發(fā)現(xiàn)包不是發(fā)給自己的,會(huì)調(diào)用ICMP消息回傳給請(qǐng)求發(fā)送方,IMCP的消息格式如下:

    另外接收到的網(wǎng)絡(luò)請(qǐng)求可能會(huì)因?yàn)閿?shù)據(jù)包過(guò)大出現(xiàn)IP分片,分片的包會(huì)在 IP 頭部的標(biāo)志字段中進(jìn)行標(biāo)記,IP模塊會(huì)把分片過(guò)的包暫存內(nèi)部?jī)?nèi)存空間,等相同ID的包全部接收到緩沖區(qū)之后再拼接。

    怎么保證拼接的順序正確呢?可以查看前文IP 頭部還有一個(gè)分片偏移量(fragment offset)字段,它 表示當(dāng)前分片在整個(gè)包中所處的位置。

    IP模塊完成數(shù)據(jù)分片重組之后,數(shù)據(jù)包交給TCP模塊操作,TCP還會(huì)再次檢查一遍請(qǐng)求方和接收方的IP信息,以及獲取端口號(hào)找到對(duì)應(yīng)的套接字,找到套接字之后根據(jù)應(yīng)用程序的類型進(jìn)行不同的操作,這個(gè)過(guò)程可能是建立連接,也可能是完成應(yīng)用程序數(shù)據(jù)的讀寫操作。

    這里可能會(huì)覺(jué)得IP檢查不是IP模塊的操作么,TCP去看IP模塊的信息是不是“越權(quán)”了?實(shí)際上這是一種性能開銷都考慮而違反“迪米特法則(Law of Demeter)”的一種特例。因?yàn)門CP模塊需要頻繁使用IP模塊的信息,如果老是需要數(shù)據(jù)之間的交互傳輸非常影響性能。

    UDP協(xié)議收發(fā)操作

    TCP/IP為了保證數(shù)據(jù)準(zhǔn)確收發(fā)需要使用一系列復(fù)雜的模塊和過(guò)程配合保證數(shù)據(jù)的完整傳輸,但是有時(shí)候有些應(yīng)用程序?yàn)榱吮WC高效會(huì)舍棄使用TCP這種復(fù)雜的機(jī)制。

    UDP協(xié)議的要點(diǎn)是盡可能將所有的數(shù)據(jù)通過(guò)一個(gè)包解決,UDP 沒(méi)有 TCP 的接收確認(rèn)、窗口等機(jī)制,因此在收發(fā)數(shù)據(jù)之前也不 需要交換控制信息。UDP的實(shí)現(xiàn)非常簡(jiǎn)單只需要應(yīng)用程序加入頭部,直接交給IP模塊完成即可,接收方也只需要檢查IP頭部的發(fā)送方和接收方的IP地址信息,然后再?gòu)腢DP找到端口號(hào),最后再找到套接字信息把數(shù)據(jù)給應(yīng)用程序。

    因?yàn)閁DP不保證傳輸?shù)姆€(wěn)定性所以無(wú)論包是否接收到都無(wú)關(guān)緊要,只要對(duì)方?jīng)]有回應(yīng)直接把包進(jìn)行重發(fā)即可。這種不需要保證傳輸穩(wěn)定性的場(chǎng)景還是有不少的,比如聊天數(shù)據(jù)、音頻和視頻信息,即使丟失一點(diǎn)點(diǎn)也沒(méi)有關(guān)系,最多是卡頓一下而已。

    關(guān)鍵:UDP 可發(fā)送的數(shù)據(jù)最大長(zhǎng)度為 IP 包的最大長(zhǎng)度減去 IP 頭部和 UDP 頭部 的長(zhǎng)度。一般來(lái)說(shuō) IP 頭部為 20 字節(jié),UDP 頭部為 8 字節(jié),因此 UDP 的最大數(shù)據(jù)長(zhǎng)度為 65507 字節(jié)。

    下面是UDP的頭部信息:

    小結(jié)

    在第二章我們了解Socket鏈接的步驟和大致細(xì)節(jié),另外介紹了整個(gè)互聯(lián)網(wǎng)比較重要的兩個(gè)協(xié)議TCP協(xié)議和IP協(xié)議,在兩個(gè)協(xié)議中需要重點(diǎn)掌握頭部設(shè)計(jì),IP模塊完成TCP模塊的數(shù)據(jù),TCP數(shù)據(jù)封裝應(yīng)用程序數(shù)據(jù),之后還需要配合Mac以太網(wǎng)模塊完成網(wǎng)絡(luò)包的最后封裝,等一切準(zhǔn)備工作完成之后,由網(wǎng)卡以及驅(qū)動(dòng)程序把整個(gè)包發(fā)送出去,所以其實(shí)可以看到?jīng)Q定你能不能上網(wǎng)等實(shí)際上是網(wǎng)卡和驅(qū)動(dòng)(這不是廢話),但是這些內(nèi)容屬于不同層級(jí)的內(nèi)容,需要一一消化。

    介紹了TCP之后,在在第二章最后部分簡(jiǎn)單提到了UDP協(xié)議,UDP是一種簡(jiǎn)單暴力的協(xié)議,設(shè)計(jì)的目的是讓所有的數(shù)據(jù)盡可能通過(guò)一個(gè)包完成,所以他不需要鏈接也不需要保證數(shù)據(jù)安全傳輸,數(shù)據(jù)丟了直接傳輸即可,UDP的應(yīng)用也是十分廣泛的,比如游戲,視頻,音樂(lè)等等數(shù)據(jù)的傳輸,很多時(shí)候丟一點(diǎn)根本無(wú)關(guān)緊要,因?yàn)榧词拐一貋?lái)這些數(shù)據(jù)也沒(méi)有意義。

    TCP/IP連接也只是互聯(lián)網(wǎng)數(shù)據(jù)傳輸?shù)囊恍〔糠郑谴_實(shí)最為核心的部分,雖然往下還有以太網(wǎng)和網(wǎng)卡以及網(wǎng)絡(luò)通信如何上網(wǎng)等細(xì)節(jié),但是只有深刻了解TCP/IP協(xié)議才能了解整個(gè)互聯(lián)網(wǎng)是如何交互和數(shù)據(jù)傳輸?shù)摹?/p>

    鄭重聲明:本文內(nèi)容及圖片均整理自互聯(lián)網(wǎng),不代表本站立場(chǎng),版權(quán)歸原作者所有,如有侵權(quán)請(qǐng)聯(lián)系管理員(admin#wlmqw.com)刪除。
    上一篇 2022年6月22日 21:08
    下一篇 2022年6月22日 21:09

    相關(guān)推薦

    聯(lián)系我們

    聯(lián)系郵箱:admin#wlmqw.com
    工作時(shí)間:周一至周五,10:30-18:30,節(jié)假日休息