世界上幾乎所有的 HTTP 通信都是由 TCP/IP 承載的,TCP/IP 是全球計(jì)算機(jī)及網(wǎng)絡(luò)設(shè)備都 在使用的一種常用的分組交換網(wǎng)絡(luò)分層協(xié)議集。客戶端應(yīng)用程序可以打開一條 TCP/IP 連 接,連接到可能運(yùn)行在世界任何地方的服務(wù)器應(yīng)用程序。一旦連接建立起來(lái)了,在客戶端 和服務(wù)器的計(jì)算機(jī)之間交換的報(bào)文就永遠(yuǎn)不會(huì)丟失、受損或失序。
盡管報(bào)文不會(huì)丟失或受損,但如果計(jì)算機(jī)或網(wǎng)絡(luò)崩潰了,客戶端和服務(wù)器之間的通信仍然會(huì)被斷開。在這種情況下, 會(huì)通知客戶端和服務(wù)器通信中斷了。
當(dāng)瀏覽器收到一個(gè) URL 的時(shí)候,會(huì)執(zhí)行幾個(gè)相對(duì)應(yīng)的步驟,如下
1.1、TCP 連接的基本知識(shí)
TCP 是可靠的數(shù)據(jù)管道
TCP 會(huì)按序、無(wú)差錯(cuò)地承載 HTTP 數(shù)據(jù),TCP 為 HTTP 提供了一條可靠的比特傳輸管道。從 TCP 連接一端填入的字節(jié)會(huì)從另一端 以原有的順序、正確地傳送出來(lái)。
TCP 流是分段的、由 IP 分組傳送
TCP 的數(shù)據(jù)是通過(guò)名為 IP 分組(或 IP 數(shù)據(jù)報(bào))的小數(shù)據(jù)塊來(lái)發(fā)送的。
這樣的話,如圖 HTTP 就是 “HTTP over TCP over IP” 這個(gè)“協(xié)議棧”中的最頂層了。其安全版本 HTTPS 就是在 HTTP 和 TCP 之間插入了一個(gè)(稱為 TLS 或 SSL 的)密碼加密層(安全層),就是在圖中的右半部分。
HTTP 要傳送一條報(bào)文時(shí),會(huì)以流的形式將報(bào)文數(shù)據(jù)的內(nèi)容通過(guò)一條打開的 TCP 連接按 序傳輸。TCP 收到數(shù)據(jù)流之后,會(huì)將數(shù)據(jù)流砍成被稱作段的小數(shù)據(jù)塊,并將段封裝在 IP 分組中,通過(guò)因特網(wǎng)進(jìn)行傳輸,如下圖中大家看到的內(nèi)容:
每個(gè) TCP 段都是由 IP 分組承載,從一個(gè) IP 地址發(fā)送到另一個(gè) IP 地址的。
而每個(gè) IP 分組中都包括:
IP 首部包含了源和目的 IP 地址、長(zhǎng)度和其他一些標(biāo)記。TCP 段的首部包含了 TCP 端口 號(hào)、TCP 控制標(biāo)記,以及用于數(shù)據(jù)排序和完整性檢查的一些數(shù)字值。
保持 TCP 連接的持續(xù)不間斷地運(yùn)行
在任意時(shí)刻計(jì)算機(jī)都可以有幾條 TCP 連接處于打開狀態(tài)。TCP 是通過(guò)端口號(hào)來(lái)保持所有 這些連接的正確運(yùn)行的。端口號(hào)和雇員使用的電話分機(jī)號(hào)很類似。
這就和我之前舉得例子是一樣的,公司的總機(jī)和你自己的座機(jī)一樣,公司的總機(jī)號(hào)碼能將你接到前臺(tái),而分機(jī)號(hào) 可以將你接到正確的雇員位置一樣,IP 地址可以將你連接到正確的計(jì)算機(jī),而端口號(hào)則 可以將你連接到正確的應(yīng)用程序上去。TCP 連接是通過(guò) 4 個(gè)值來(lái)識(shí)別的:
源IP 地址、源端口號(hào)、目的IP 地址、目的端口號(hào)
這 4 個(gè)值一起唯一地定義了一條連接。兩條不同的 TCP 連接不能擁有 4 個(gè)完全相同的地 址組件值(但不同連接的部分組件可以擁有相同的值)。
這里需要我們注意的是,有些連接共享了相同的目的端口號(hào),有些連接使用了相同的源 IP 地址,有些使用了相同的目的 IP 地址,但沒有兩個(gè)不同連接所有的 4 個(gè)值都一樣。
TCP 套接字
操作系統(tǒng)提供了一些操縱其 TCP 連接的工具。為了更具體地說(shuō)明問(wèn)題,我們來(lái)看一個(gè) TCP 編程接口,這些套接字我就不一一介紹了,我給大家一個(gè)表格,大家可以理解一下
套接字API調(diào)用描 述s = socket()創(chuàng)建一個(gè)新的、未命名、未關(guān)聯(lián)的套接字bind(s,)向套接字賦一個(gè)本地端口號(hào)和接口connect(s,)創(chuàng)建一條連接本地套接字與遠(yuǎn)程主機(jī)及端口的連接listen(s,...)標(biāo)識(shí)一個(gè)本地套接字,使其可以合法接受連接s2 = accept(s)等待某人建立一條到本地端口的連接
套接字 API 允許用戶創(chuàng)建 TCP 的端點(diǎn)數(shù)據(jù)結(jié)構(gòu),將這些端點(diǎn)與遠(yuǎn)程服務(wù)器的 TCP 端點(diǎn)進(jìn) 行連接,并對(duì)數(shù)據(jù)流進(jìn)行讀寫。TCP API 隱藏了所有底層網(wǎng)絡(luò)協(xié)議的握手細(xì)節(jié),以及 TCP 數(shù)據(jù)流與 IP 分組之間的分段和重裝細(xì)節(jié)。
TCP 客戶端和服務(wù)器是如何通過(guò) TCP 套接字接口進(jìn)行通信的
上圖中說(shuō)明了可以怎樣通過(guò)套接字 API 來(lái)凸顯客戶端和服務(wù)器在實(shí)現(xiàn) HTTP 事務(wù)時(shí)所應(yīng)執(zhí)行的步驟。
TCP 連接握手需要經(jīng)過(guò)以下幾個(gè)步驟。如圖所示:
請(qǐng)求新的 TCP 連接時(shí),客戶端要向服務(wù)器發(fā)送一個(gè)小的 TCP 分組(通常是 40 ~ 60 個(gè)字節(jié))。這個(gè)分組中設(shè)置了一個(gè)特殊的 SYN 標(biāo)記,說(shuō)明這是一個(gè)連接請(qǐng)求。
我們永遠(yuǎn)不會(huì)看到這些分組——這些分組都由 TCP/IP 軟件管理,對(duì)其是不可見 的。HTTP 程序員看到的只是創(chuàng)建 TCP 連接時(shí)存在的時(shí)延。
在這里我們需要注意的就是 TCP 連接的握手時(shí)延,通常 HTTP 事務(wù)都不會(huì)交換太多數(shù)據(jù),此時(shí),SYN/SYN+ACK 握手(參見圖中的 a 段 和圖中的 b 段)會(huì)產(chǎn)生一個(gè)可測(cè)量的時(shí)延。TCP 連接的 ACK 分組(參見圖中的 c 段)通常都足夠大,可以承載整個(gè) HTTP 請(qǐng)求報(bào)文,而且很多 HTTP 服務(wù)器響應(yīng)報(bào)文都可 以放入一個(gè) IP 分組 中去(比如,響應(yīng)是包含了裝飾性圖片的小型 HTML 文件,或者是對(duì)瀏覽器高速緩存請(qǐng)求產(chǎn)生的 304 Not Modified 響應(yīng))。
TCP 慢啟動(dòng)
TCP 數(shù)據(jù)傳輸?shù)男阅苓€取決于 TCP 連接的使用期(age)。TCP 連接會(huì)隨著時(shí)間進(jìn)行自 我“調(diào)諧”,起初會(huì)限制連接的最大速度,如果數(shù)據(jù)成功傳輸,會(huì)隨著時(shí)間的推移提高傳輸 的速度。這種調(diào)諧被稱為 TCP 慢啟動(dòng)(slow start),用于防止因特網(wǎng)的突然過(guò)載和擁 塞。
TCP 慢啟動(dòng)限制了一個(gè) TCP 端點(diǎn)在任意時(shí)刻可以傳輸?shù)姆纸M數(shù)。簡(jiǎn)單來(lái)說(shuō),每成功接收 一個(gè)分組,發(fā)送端就有了發(fā)送另外兩個(gè)分組的權(quán)限。如果某個(gè) HTTP 事務(wù)有大量數(shù)據(jù)要發(fā) 送,是不能一次將所有分組都發(fā)送出去的。必須發(fā)送一個(gè)分組,等待確認(rèn);然后可以發(fā)送 兩個(gè)分組,每個(gè)分組都必須被確認(rèn),這樣就可以發(fā)送四個(gè)分組了,以此類推。這種方式被 稱為“打開擁塞窗口”。
由于存在這種擁塞控制特性,所以新連接的傳輸速度會(huì)比已經(jīng)交換過(guò)一定量數(shù)據(jù)的、“已 調(diào)諧”連接慢一些。由于已調(diào)諧連接要更快一些,所以 HTTP 中有一些可以重用現(xiàn)存連接 的工具。
前面我們說(shuō)了 TCP 連接,我們重新來(lái)分析一下 HTTP ,之前我也說(shuō)過(guò)在 HTTP 1.0的時(shí)候和1.1之后,有 Keep-Alive ,關(guān)于 Keep-Alive 不懂的請(qǐng)翻看前面的公眾號(hào)的文章內(nèi)容,接下來(lái)我分幾個(gè)內(nèi)容給大家講述 HTTP 對(duì)連接上的處理。
我們來(lái)看一下串行:
每個(gè)事務(wù)都需要(串行地建立)一條 新的連接,那么連接時(shí)延和慢啟動(dòng)時(shí)延就會(huì)疊加起來(lái)
并行連接就是說(shuō) HTTP 允許客戶端打開多條連接,并行的去執(zhí)行多個(gè) HTTP 的事務(wù),就會(huì)出現(xiàn)多條線路平行的情況。
其實(shí)并行連接并沒有說(shuō)是頁(yè)面的傳輸速度,是因?yàn)槎鄠€(gè)對(duì)象同時(shí)在進(jìn)展,所以,他的速度要比疊加起來(lái),讓你在感覺上快不少。
持久連接
HTTP 1.1 允許 HTTP 設(shè)備在事務(wù)處理結(jié)束之后 將 TCP 連接保持在打開狀態(tài),以便為未來(lái)的 HTTP 請(qǐng)求重用現(xiàn)存的連接。在事務(wù)處理結(jié)束之后仍然保持在打開狀態(tài)的 TCP 連接被稱為持久連接。非持久連接會(huì)在每個(gè)事務(wù)結(jié)束之后關(guān)閉。持久連接會(huì)在不同事務(wù)之間保持打開狀態(tài),直到客戶端或服務(wù)器決定將其關(guān)閉為止。
管道化連接(也有人稱之為管線化)
HTTP/1.1 允許在持久連接上可選地使用請(qǐng)求管道。這是相對(duì)于 keep-alive 連接的又一性能優(yōu)化。在響應(yīng)到達(dá)之前,可以將多條請(qǐng)求放入隊(duì)列。當(dāng)?shù)谝粭l請(qǐng)求通過(guò)網(wǎng)絡(luò)流向地球另一端的服務(wù)器時(shí),第二條和第三條請(qǐng)求也可以開始發(fā)送了。在高時(shí)延網(wǎng)絡(luò)條件下,這樣做可以降低網(wǎng)絡(luò)的環(huán)回時(shí)間,提高性能。
其實(shí)管道化說(shuō)白了就是 傳送過(guò)程中不需先等待服務(wù)端的回應(yīng),然后又發(fā)了幾條,瀏覽器將 HTTP 要求大批提交可大幅縮短頁(yè)面的加載時(shí)間,特別是在傳輸延遲(lag/latency)較高的情況下(如衛(wèi)星連接)。此技術(shù)之關(guān)鍵在于多個(gè) HTTP 的要求消息可以同時(shí)塞入一個(gè) TCP 分組中,所以只提交一個(gè)分組即可同時(shí)發(fā)出多個(gè)要求,借此可減少網(wǎng)絡(luò)上多余的分組并降低線路負(fù)載。
Modbus由MODICON公司于1979年開發(fā),是一種工業(yè)現(xiàn)場(chǎng)總線協(xié)議標(biāo)準(zhǔn)。1996年施耐德公司推出基于以太網(wǎng)TCP/IP的Modbus協(xié)議:ModbusTCP。
Modbus協(xié)議是一項(xiàng)應(yīng)用層報(bào)文傳輸協(xié)議,包括ASCII、RTU、TCP三種報(bào)文類型。
標(biāo)準(zhǔn)的Modbus協(xié)議物理層接口有RS232、RS422、RS485和以太網(wǎng)接口,采用master/slave方式通信。
ModbusTCP的數(shù)據(jù)幀可分為兩部分:MBAP+PDU。
報(bào)文頭MBAP
MBAP為報(bào)文頭,長(zhǎng)度為7字節(jié),組成如下:
事務(wù)處理標(biāo)識(shí) | 協(xié)議標(biāo)識(shí) | 長(zhǎng)度 | 單元標(biāo)識(shí)符 |
2字節(jié) | 2字節(jié) | 2字節(jié) | 1字節(jié) |
內(nèi)容 | 解釋 |
事務(wù)處理標(biāo)識(shí) | 可以理解為報(bào)文的序列號(hào),一般每次通信之后就要加1以區(qū)別不同的通信數(shù)據(jù)報(bào)文。 |
協(xié)議標(biāo)識(shí)符 | 00 00表示ModbusTCP協(xié)議。 |
長(zhǎng)度 | 表示接下來(lái)的數(shù)據(jù)長(zhǎng)度,單位為字節(jié)。 |
單元標(biāo)識(shí)符 | 可以理解為設(shè)備地址。 |
幀結(jié)構(gòu)PDU
PDU由功能碼+數(shù)據(jù)組成。功能碼為1字節(jié),數(shù)據(jù)長(zhǎng)度不定,由具體功能決定。
功能碼
Modbus的操作對(duì)象有四種:線圈、離散輸入、保持寄存器、輸入寄存器。
對(duì)象 | 含義 |
線圈 | PLC的輸出位,開關(guān)量,在Modbus中可讀可寫 |
離散量 | PLC的輸入位,開關(guān)量,在Modbus中只讀 |
輸入寄存器 | PLC中只能從模擬量輸入端改變的寄存器,在Modbus中只讀 |
保持寄存器 | PLC中用于輸出模擬量信號(hào)的寄存器,在Modbus中可讀可寫 |
根據(jù)對(duì)象的不同,Modbus的功能碼有:
功能碼 | 含義 |
0x01 | 讀線圈 |
0x05 | 寫單個(gè)線圈 |
0x0F | 寫多個(gè)線圈 |
0x02 | 讀離散量輸入 |
0x04 | 讀輸入寄存器 |
0x03 | 讀保持寄存器 |
0x06 | 寫單個(gè)保持寄存器 |
0x10 | 寫多個(gè)保持寄存器 |
說(shuō)明更詳細(xì)的表
代碼 | 中文名稱 | 英文名 | 位操作/字操作 | 操作數(shù)量 |
01 | 讀線圈狀態(tài) | READ COIL STATUS | 位操作 | 單個(gè)或多個(gè) |
02 | 讀離散輸入狀態(tài) | READ INPUT STATUS | 位操作 | 單個(gè)或多個(gè) |
03 | 讀保持寄存器 | READ HOLDING REGISTER | 字操作 | 單個(gè)或多個(gè) |
04 | 讀輸入寄存器 | READ INPUT REGISTER | 字操作 | 單個(gè)或多個(gè) |
05 | 寫線圈狀態(tài) | WRITE SINGLE COIL | 位操作 | 單個(gè) |
06 | 寫單個(gè)保持寄存器 | WRITE SINGLE REGISTER | 字操作 | 單個(gè) |
15 | 寫多個(gè)線圈 | WRITE MULTIPLE COIL | 位操作 | 多個(gè) |
16 | 寫多個(gè)保持寄存器 | WRITE MULTIPLE REGISTER | 字操作 | 多個(gè) |
0x01:讀線圈
在從站中讀1~2000個(gè)連續(xù)線圈狀態(tài),ON=1,OFF=0
0x05:寫單個(gè)線圈
將從站中的一個(gè)輸出寫成ON或OFF,0xFF00請(qǐng)求輸出為ON,0x000請(qǐng)求輸出為OFF
0x0F:寫多個(gè)線圈
將一個(gè)從站中的一個(gè)線圈序列的每個(gè)線圈都強(qiáng)制為ON或OFF,數(shù)據(jù)域中置1的位請(qǐng)求相應(yīng)輸出位ON,置0的位請(qǐng)求響應(yīng)輸出為OFF
0x02:讀離散量輸入
從一個(gè)從站中讀1~2000個(gè)連續(xù)的離散量輸入狀態(tài)
0x04:讀輸入寄存器
從一個(gè)遠(yuǎn)程設(shè)備中讀1~2000個(gè)連續(xù)輸入寄存器
0x03:讀保持寄存器
從遠(yuǎn)程設(shè)備中讀保持寄存器連續(xù)塊的內(nèi)容
0x06:寫單個(gè)保持寄存器
在一個(gè)遠(yuǎn)程設(shè)備中寫一個(gè)保持寄存器
0x10:寫多個(gè)保持寄存器
在一個(gè)遠(yuǎn)程設(shè)備中寫連續(xù)寄存器塊(1~123個(gè)寄存器)
ModBusTcp與串行鏈路Modbus的數(shù)據(jù)域是一致的,具體數(shù)據(jù)域可以參考串行Modbus。這里給出幾個(gè)ModbusTcp的鏈路解析說(shuō)明,輔助新人分析報(bào)文。
功能碼 0x10:寫多個(gè)保持寄存器,上面2個(gè)圖片都寫錯(cuò)了
通信方式
Modbus設(shè)備可分為主站(poll)和從站(slave)。主站只有一個(gè),從站有多個(gè),主站向各從站發(fā)送請(qǐng)求幀,從站給予響應(yīng)。在使用TCP通信時(shí),主站為client端,主動(dòng)建立連接;從站為server端,等待連接。
IANA(Internet Assigned Numbers Authority,互聯(lián)網(wǎng)編號(hào)分配管理機(jī)構(gòu))給Modbus協(xié)議賦予TCP端口號(hào)為502,這是目前在儀表與自動(dòng)化行業(yè)中唯一分配到的端口號(hào)。
通信過(guò)程
在工業(yè)自動(dòng)化控制中,經(jīng)常會(huì)遇到開關(guān)量,數(shù)字量,模擬量,離散量,脈沖量等各種概念,而人們?cè)趯?shí)際應(yīng)用中,對(duì)于這些概念又很容易混淆。現(xiàn)將各種概念羅列如下:
1.開關(guān)量:
一般指的是觸點(diǎn)的“開”與“關(guān)”的狀態(tài),一般在計(jì)算機(jī)設(shè)備中也會(huì)用“0”或“1”來(lái)表示開關(guān)量的狀態(tài)。開關(guān)量分為有源開關(guān)量信號(hào)和無(wú)源開關(guān)量信號(hào),有源開關(guān)量信號(hào)指的是“開”與“關(guān)”的狀態(tài)是帶電源的信號(hào),專業(yè)叫法為躍階信號(hào),可以理解為脈沖量,一般的都有220VAC,?110VAC,24VDC,12VDC等信號(hào),無(wú)源開關(guān)量信號(hào)指的是“開”和“關(guān)”的狀態(tài)時(shí)不帶電源的信號(hào),一般又稱之為干接點(diǎn)。電阻測(cè)試法為電阻0或無(wú)窮大。
2.數(shù)字量:
很多人會(huì)將數(shù)字量與開關(guān)量混淆,也將其與模擬量混淆。數(shù)字量在時(shí)間和數(shù)量上都是離散的物理量,其表示的信號(hào)則為數(shù)字信號(hào)。數(shù)字量是由0和1組成的信號(hào),經(jīng)過(guò)編碼形成有規(guī)律的信號(hào),量化后的模擬量就是數(shù)字量。
3.模擬量:
模擬量的概念與數(shù)字量相對(duì)應(yīng),但是經(jīng)過(guò)量化之后又可以轉(zhuǎn)化為數(shù)字量。模擬量是在時(shí)間和數(shù)量上都是連續(xù)的物理量,其表示的信號(hào)則為模擬信號(hào)。模擬量在連續(xù)的變化過(guò)程中任何一個(gè)取值都是一個(gè)具體有意義的物理量,如溫度,電壓,電流等。
4.離散量:
離散量是將模擬量離散化之后得到的物理量。即任何儀器設(shè)備對(duì)于模擬量都不可能有個(gè)完全精確的表示,因?yàn)樗麄兌加幸粋€(gè)采樣周期,在該采樣周期內(nèi),其物理量的數(shù)值都是不變的,而實(shí)際上的模擬量則是變化的。這樣就將模擬量離散化,成為了離散量。
5.脈沖量:
脈沖量就是瞬間電壓或電流由某一值躍變到另一值的信號(hào)量。在量化后,其變化持續(xù)有規(guī)律就是數(shù)字量,如果其由0變成某一固定值并保持不變,其就是開關(guān)量。
綜上所述,模擬量就是在某個(gè)過(guò)程中時(shí)間和數(shù)量連續(xù)變化的物理量,由于在實(shí)際的應(yīng)用中,所有的儀器設(shè)備對(duì)于外界數(shù)據(jù)的采集都有一個(gè)采樣周期,其采集的數(shù)據(jù)只有在下一個(gè)采樣周期開始時(shí)才有變動(dòng),采樣周期內(nèi)其數(shù)值并不隨模擬量的變化而變動(dòng)。
這樣就將模擬量離散化了,例如:某設(shè)備的采樣周期為1秒,其在第五秒的時(shí)間采集的溫度為35度,而第六秒的溫度為36度,該設(shè)備就只能標(biāo)稱第五秒時(shí)間溫度35度,第六秒時(shí)間溫度36度,而第五點(diǎn)五秒的時(shí)間其標(biāo)稱也只是35度,但是其實(shí)際的模擬量是35.5度。這樣就將模擬信號(hào)離散化。其采集的數(shù)據(jù)就是離散化了,不再是連續(xù)的模擬量信號(hào)。
由于計(jì)算機(jī)只識(shí)別0和1兩個(gè)信號(hào),即開關(guān)量信號(hào),用其來(lái)表示數(shù)值都是使用數(shù)字串來(lái)表示,由于計(jì)算能力的問(wèn)題,其數(shù)字串不能無(wú)限長(zhǎng),即其表達(dá)的精度也是有限的,同樣的以溫度為例,由于數(shù)字串限制,其表達(dá)溫度的精度只能達(dá)到0.1度,小于該單位的數(shù)值則不能被標(biāo)稱,這樣就必須將離散量進(jìn)行量化,將其變?yōu)閿?shù)字量。即35.68度的溫度則表示為35.6度。
免責(zé)聲明:本文轉(zhuǎn)自網(wǎng)絡(luò),版權(quán)歸原作者所有,如涉及作品版權(quán)問(wèn)題,請(qǐng)及時(shí)與我們聯(lián)系刪除,謝謝!
16款電工仿真軟件
者公眾號(hào):org_yijiaoqian
兩臺(tái)主機(jī)間會(huì)通過(guò)非常多網(wǎng)絡(luò)設(shè)備,不管哪個(gè)網(wǎng)絡(luò)設(shè)備都會(huì)發(fā)生數(shù)據(jù)丟失,如果發(fā)生數(shù)據(jù)丟失的話,會(huì)發(fā)生數(shù)據(jù)重傳,會(huì)出現(xiàn)數(shù)據(jù)重復(fù)(之前丟失的包并不是丟失而是產(chǎn)生了延時(shí))。數(shù)據(jù)傳輸?shù)慕橘|(zhì)也可能多樣,如內(nèi)網(wǎng)里通過(guò)網(wǎng)線進(jìn)行傳輸,連接到公網(wǎng)的話會(huì)通過(guò)光纖進(jìn)行連接,所以要實(shí)現(xiàn)不同介質(zhì)間信號(hào)的轉(zhuǎn)換,還有從光纖到路由器無(wú)線脈沖轉(zhuǎn)換,距離遠(yuǎn)的話還有信號(hào)衰減問(wèn)題。所以在網(wǎng)絡(luò)傳輸過(guò)程中有非常多的問(wèn)題需要解決,把問(wèn)題分組分層,不同層次間解決不同問(wèn)題,不同層次間定義標(biāo)準(zhǔn)化接口讓它們間可以進(jìn)行數(shù)據(jù)的通信。
為了簡(jiǎn)化網(wǎng)絡(luò)的復(fù)雜度,網(wǎng)絡(luò)通信的不同方面被分解為多層次結(jié)構(gòu),每一層只與緊挨著的上層或者下層進(jìn)行交互,將網(wǎng)絡(luò)分層,這樣就可以修改,甚至替換某一層的軟件,只要層與層之間的接口保持不變,就不會(huì)影響到其他層。
是OSI的一種實(shí)現(xiàn),包括應(yīng)用層、運(yùn)輸層、網(wǎng)際層和網(wǎng)絡(luò)接口層。
如上圖右邊一個(gè)服務(wù)器部署了一個(gè)靜態(tài)頁(yè)面,通過(guò)nginx部署在公網(wǎng)上,瀏覽器通過(guò)域名對(duì)它進(jìn)行訪問(wèn),瀏覽器輸入域名點(diǎn)回車后是怎么工作的呢?
http://www.dumain.com
服務(wù)端只認(rèn)ip地址,瀏覽器將域名解析出來(lái),看下瀏覽器里有沒有域名對(duì)應(yīng)DNS的緩存,有的話直接拿到服務(wù)端的ip地址,沒有的話去本地的host文件看有沒有配置,沒有配置的話才會(huì)發(fā)起一個(gè)DNS請(qǐng)求用來(lái)獲取服務(wù)器ip地址。
DNS也是臺(tái)服務(wù)器也有自己的ip地址,這時(shí)候應(yīng)用層會(huì)構(gòu)造一個(gè)DNS請(qǐng)求報(bào)文,應(yīng)用層會(huì)去調(diào)用傳輸層的接口一個(gè)socket的API,DNS默認(rèn)使用UDP實(shí)現(xiàn)數(shù)據(jù)傳輸,即應(yīng)用層調(diào)用傳輸層的API,傳輸層會(huì)在DNS請(qǐng)求報(bào)文基礎(chǔ)上加一個(gè)UDP的請(qǐng)求頭,傳輸層將數(shù)據(jù)交給網(wǎng)絡(luò)層,網(wǎng)絡(luò)層同樣在UDP請(qǐng)求報(bào)文基礎(chǔ)上加IP的請(qǐng)求頭,網(wǎng)絡(luò)層會(huì)將IP請(qǐng)求報(bào)文交給數(shù)據(jù)鏈路層,數(shù)據(jù)鏈路層會(huì)將自己的mac頭加上去并把對(duì)應(yīng)的請(qǐng)求報(bào)文交給下一個(gè)機(jī)器的mac地址也會(huì)加上去,下一個(gè)機(jī)器的mac地址通過(guò)網(wǎng)絡(luò)層ARP協(xié)議找到,ARP會(huì)發(fā)送一些請(qǐng)求看下你對(duì)應(yīng)的ip地址的mac地址是多少,最后通過(guò)物理層物理介質(zhì)傳出去,通常傳到路由器上.
路由器是三層設(shè)備(從下向上)從物理層開始連接,物理層交給數(shù)據(jù)鏈路層,數(shù)據(jù)鏈路層看下地址是不是給我的,是給我的進(jìn)行解析,不是給我的就丟棄,報(bào)文再傳給上面一層網(wǎng)絡(luò)層,網(wǎng)絡(luò)層把數(shù)據(jù)傳到下一個(gè)路由器的地址是多少,會(huì)通過(guò)運(yùn)營(yíng)商的網(wǎng)絡(luò)接口傳到運(yùn)營(yíng)商的路由器上,運(yùn)營(yíng)商有自己的DNS服務(wù)器,如果配置的是運(yùn)營(yíng)商自己的DNS服務(wù)器的話會(huì)直接在這個(gè)DNS服務(wù)器里找自己對(duì)應(yīng)的域名拿到對(duì)應(yīng)的ip地址,也就是剛請(qǐng)求DNS報(bào)文地址,然后原路返回解析直到應(yīng)用層拿到剛域名對(duì)應(yīng)的ip地址,這樣就可以進(jìn)行HTTP請(qǐng)求報(bào)文的發(fā)送,再調(diào)用傳輸層協(xié)議是TCP參數(shù),同樣每到一層加頭。
超文本傳輸協(xié)議,是一個(gè)基于請(qǐng)求與響應(yīng),無(wú)狀態(tài)的,應(yīng)用層的協(xié)議,常基于TCP/IP協(xié)議傳輸數(shù)據(jù),互聯(lián)網(wǎng)上應(yīng)用最為廣泛的一種網(wǎng)絡(luò)協(xié)議,所有的WWW文件都必須遵守這個(gè)標(biāo)準(zhǔn)。設(shè)計(jì)HTTP的初衷是為了提供一種發(fā)布和接收HTML頁(yè)面的方法。
HTTP協(xié)議版本已經(jīng)演化到3.0版本,關(guān)于協(xié)議版本可以查看 快速掌握HTTP1.0 1.1 2.0 3.0的特點(diǎn)及其區(qū)別
HTTP 協(xié)議的請(qǐng)求報(bào)文和響應(yīng)報(bào)文的結(jié)構(gòu)基本相同,由三大部分組成:
其中起始行和頭部的字段并成為 請(qǐng)求頭 或者 響應(yīng)頭,統(tǒng)稱為 Header;消息正文也叫實(shí)體,稱為 body。HTTP 協(xié)議規(guī)定每次發(fā)送的報(bào)文必須要有 Header,但是可以沒有 body,也就是說(shuō)頭信息是必須的,實(shí)體信息可以沒有。而且在 header 和 body 之間必須要有一個(gè)空行(CRLF)。
頭部字段是 key-value 的形式,key 和 value 之間用“:”分隔,最后用 CRLF 換行表示字
段結(jié)束。比如前后分離時(shí)經(jīng)常遇到的要與后端協(xié)商傳輸數(shù)據(jù)的類型“Content-type: application/json”,這里 key 就是“Content-type”,value 就 是“application/json”。HTTP 頭字段非常靈活,不僅可以使用標(biāo)準(zhǔn)里的 Host、 Connection 等已有頭,也可以任意添加自定義頭,這就給 HTTP 協(xié)議帶來(lái)了無(wú)限的擴(kuò)展可能。
頭字段注意事項(xiàng)
HTTP 協(xié)議中有非常多的頭字段,但基本上可以分為四大類:通用標(biāo)頭、實(shí)體標(biāo)頭、請(qǐng)求標(biāo)頭、響應(yīng)標(biāo)頭。
HTTP 頭字段更多內(nèi)容請(qǐng)查看《深入掌握HTTP四種標(biāo)頭基本概念 》
TCP(Transmission Control Protocol),傳輸控制協(xié)議:面向連接的,可靠的,基于字節(jié)流的傳輸層通信協(xié)議。它能幫助你確定計(jì)算機(jī)連接到 Internet 以及它們之間的數(shù)據(jù)傳輸。通過(guò)三次握手來(lái)建立 TCP 連接,三次握手就是用來(lái)啟動(dòng)和確認(rèn) TCP 連接的過(guò)程。一旦連接建立后,就可以發(fā)送數(shù)據(jù)了,當(dāng)數(shù)據(jù)傳輸完成后,會(huì)通過(guò)關(guān)閉虛擬電路來(lái)斷開連接。
TCP連接:四元組[ 源地址, 源端口, 目的地址, 目的端口 ]
在了解具體流程之前,我們先認(rèn)識(shí)幾個(gè)概念
最初兩端的TCP進(jìn)程都處于CLOSED關(guān)閉狀態(tài),A主動(dòng)打開連接,而B被動(dòng)打開連接。
A、B關(guān)閉狀態(tài)CLOSED — B收聽狀態(tài)LISTEN — A同步已發(fā)送狀態(tài)SYN-SENT — B同步收到狀態(tài)SYN-RCVD— A、B連接已建立狀態(tài)ESTABLISHED
B的TCP服務(wù)器進(jìn)程先創(chuàng)建傳輸控制塊TCB,準(zhǔn)備接受客戶進(jìn)程的連接請(qǐng)求。然后服務(wù)器進(jìn)程就處于LISTEN(收聽)狀態(tài),等待客戶的連接請(qǐng)求。若有,則作出響應(yīng)。
下面通過(guò)一個(gè)案例看三次握手是怎么進(jìn)行的
tcpdump -i en0 -S -c 3 port 8000
nc 192.168.109.200 8000
netstat -tpn # t:TCP連接裝,p:進(jìn)程顯示 ,n:數(shù)字形式
# 每秒查看一次
netstat -tpn -c 1
等待 2MSL后釋放連接
TCP把應(yīng)用交付的數(shù)據(jù)僅僅看成是一連串的無(wú)結(jié)構(gòu)的字節(jié)流,TCP并不 知道字節(jié)流的含義,TCP并不關(guān)心應(yīng)用程序一次將多大的報(bào)文發(fā)送到 TCP的緩存中,而是根據(jù)對(duì)方給出的窗口值和當(dāng)前網(wǎng)絡(luò)擁堵的程度來(lái)決 定一個(gè)報(bào)文段應(yīng)該包含多少個(gè)字節(jié)。
MSS: Max Segment Size, 默認(rèn) 536byte 實(shí)際數(shù)據(jù)
在網(wǎng)絡(luò)傳輸過(guò)程中可能會(huì)出現(xiàn)以下的一些情況:
停止等待協(xié)議如下:
停止等待協(xié)議,效率比較低
重傳機(jī)制如下:
滑動(dòng)窗口協(xié)議與累計(jì)確認(rèn)(延時(shí)ack)
如上效率低,所以tcp提出了新的協(xié)議-滑動(dòng)窗口協(xié)議與累計(jì)確認(rèn)(延時(shí)ack)。
滑動(dòng)窗口大小同通過(guò)tcp三次握手和對(duì)端協(xié)商,且受網(wǎng)絡(luò)狀況影響。
上面是一個(gè)一個(gè)報(bào)文,實(shí)際可發(fā)一批報(bào)文,服務(wù)器并不是挨個(gè)去確認(rèn),上面回一個(gè)ack浪費(fèi)資源,單獨(dú)響應(yīng)一個(gè)報(bào)文時(shí),tcp本身一個(gè)報(bào)文至少20個(gè)字節(jié)再加上ip頭報(bào)文20字節(jié),所以一個(gè)ack至少40字節(jié)。
所以延時(shí)ack的發(fā)送,如下圖確認(rèn)最后一個(gè)報(bào)文如5就可以,但這樣也有一個(gè)問(wèn)題如3的報(bào)文丟了,這時(shí)只能確認(rèn)1和2連續(xù)報(bào)文,從3以后的報(bào)文全要重傳,已確認(rèn)的報(bào)文在緩沖區(qū)丟棄掉。
文章持續(xù)更新,可以公眾號(hào)搜一搜「 一角錢技術(shù) 」第一時(shí)間閱讀, 本文 GitHub org_hejianhui/JavaStudy 已經(jīng)收錄,歡迎 Star。
*請(qǐng)認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。