網絡模型不是一開始就有的,在網絡剛發展時,網絡協議是由各互聯網公司本身定義的,各家的協議也是不能互通的。這樣大大的阻礙了互聯網的發展,爲了解決這個問題,國際標準化組織 1984 提出的模型標準,簡稱 OSI(Open Systems Interconnection Model)。具體以下圖:javascript
OSI七層模型每一層都有本身的做用,從上到下的做用依次爲:html
七層中應用層、表示層和會話層由軟件控制,傳輸層、網絡層和數據鏈路層由操做系統控制,物理層有物理設備控制。java
TCP/IP 模型是由 OSI 模型演化而來,TCP/IP 模型將 OSI 模型由七層簡化爲五層(一開始爲四層),應用層、表示層、會話層統一爲應用層。node
TCP/IP協議被稱爲傳輸控制協議/互聯網協議,又稱網絡通信協議(Transmission Control Protocol)。是由網絡層的IP協議和傳輸層的TCP協議組成,是一個很大的協議集合。瀏覽器
物理層和數據鏈路層沒有定義任何特定協議,支持全部的標準和專用的協議。bash
網絡層定義了網絡互聯也就是IP協議,主要包括IP、ARP、RARP、ICMP、IGMP。服務器
傳輸層定義了TCP和UDP(User Datagram Protocol),咱們會後面重點介紹一下TCP協議。網絡
應用層定義了HTTP(超文本傳輸協議)、FTP(文件傳輸協議)、DNS(域名系統)等協議。併發
計算機在傳遞數據的時候傳遞的都是0和1的數字,而物理層關心的是用什麼信號來表示0和1,是否能夠雙向通訊,最初的鏈接如何創建以及完成鏈接如何終止,總之,物理層是爲數據傳輸提供可靠的環境。curl
數據鏈路層們於物理層和網絡層之間,用來向網絡層提供數據,就是把源計算機網絡層傳過來的信息傳遞給目標主機。 數據鏈路層主要的做用包括:
網絡層位於傳輸層和數據鏈路層之間,用於把數據從源主機通過若干個中間節點傳送到目標主機,並向傳輸層提供最基礎的數據傳輸服務,它要提供路由和選址的工做。
那什麼是路由和選址呢?
選址
交換機是靠MAC來尋址的,而由於MAC地址是無層次的,因此要靠IP地址來確認計算機的位置,這就是選址。
路由
在可以選擇的多條道路之間選擇一條最短的路徑就是路由的工做。
路由和選址都離不開IP,咱們就詳細介紹一下IP頭部。
IP頭部是由20個字節組成的,具體項所佔的位數以下圖:
具體的數據咱們用Wireshark來表抓取一下,如圖(藍色部分爲IP數據包):
version - 版本
Header Length - 首部長部
Differentiated Services Field - 優先級與服務類型
Total Length - 總長度,該字段用以指示整個IP數據包的長度,最長爲65535字節,包括頭和數據。
Identification - 標識符,惟一標識主機發送的每一份數據報。
Flags - 標誌。分爲3個字段,依次爲保留位、不分片位和更多片位
Fragment offset - 段偏移量。該分片相對於原始數據報開始處位置的偏移量。
TTL(Time to Live生存時間) - 該字段用於表示IP數據包的生命週期,能夠防止一個數據包在網絡中無限循環地發下去。TTL的意思是一個數據包在被丟棄以前在網絡中的最大週轉時間。該數據包通過的每個路由器都會檢查該字段中的值,當TTL的值爲0時此數據包會被丟棄。TTL對應於一個數據包經過路由器的數目,一個數據包每通過一個路由器,TTL將減去1。
Protocol - 協議號。用以指示IP數據包中封裝的是哪一個協議。
Header checksum - 首部校驗和。檢驗和是16位的錯誤檢測字段。目的主機和網絡中的每一個網關都要從新計算報頭的校驗和,若是同樣表示沒有改動過。
Source - 源IP地址。該字段用於表示數據包的源地址,指的是發送該數據包的設備的網絡地址。
Destination - 目標IP地址。該字段用於表示數據包的目標的地址,指的是接收節點的網絡地址。
傳輸層是面向鏈接的、可靠的的進程到進程通訊的協議。TCP提供全雙工服務,即數據可在同一時間雙向傳播。TCP將若干個字節構成一個分組,此分組稱爲報文段(Segment)。提供了一種端到端的鏈接。
傳輸層的協議主要有TCP 和 UDP,TCP(Transimision Control Protocal)是一種可靠的、面向鏈接的協議,傳輸效率低。UDP(User Datagram Protocal)是一種不可靠的、無鏈接的服務,傳輸效率高。 下面重點介紹一下TCP的三次握手和四次揮手。
TCP主要是將數據進行分段打包傳輸,對每一個數據包編號控制順序,運輸中丟失、重發和丟棄處理。
有點和IP頭相似,咱們先來張圖看下:
Source Port & Destination Port - 源端口號和目標端口號;計算機經過端口號識別訪問哪一個服務,好比http服務或ftp服務;發送方端口號是進行隨機端口;目標端口號決定了接收方哪一個程序來接收。
Sequence number - 32位序列號,TCP用序列號對數據包進行標記,以便在到達目的地後從新重裝。在創建鏈接時一般由計算機生成一個隨機數做爲序列號的初始值。
Acknowledgment number - 32位確認號,確認應答號。發送端接收到這個確認應答後,能夠認爲這個位置之前全部的數據都已被正常接收。
Header Length - 首部長度。單位是 '4'個'字節',若是沒有可選字段,那麼這裏的值就是 5。表示 TCP 首部的長度爲 20 字節。
checksum - 16位校驗和。用來作差錯控制,TCP校驗和的計算包括TCP首部、數據和其它填充字節。
flags - 控制位。TCP的鏈接、傳輸和斷開都受這六個控制位的指揮
window size - 本地可接收數據的數目,這個值的大小是可變的。當網絡通暢時將這個窗口值變大加快傳輸速度,當網絡不穩定時減小這個值能夠保證網絡數據的可靠傳輸。它是來在TCP傳輸中進行流量控制的
三次握手和四次揮手究竟是怎麼回事呢,我用一臺主機A(172.16.50.72:65076)起一個服務,另一臺主機B(172.16.17.94:8080)請求一下。 在A主機上啓動node服務:
let http = require('http');
let url = require('url');
let server = http.createServer();
server.on('request', (req, res) => {
let {pathname, querry} = url.parse(req.url, true);
let result = [];
req.on('data', (data) => {
result.push(data);
})
req.on('end', () => {
console.log(Buffer.concat(result).toString());
res.end('hello world');
})
})
server.listen(8080, () => {
console.log('server started');
});
複製代碼
B主機鏈接A併發送數據:
curl -d "user":"lucy" 172.16.17.94:8080
複製代碼
用wireshark抓包演示一下。以下圖:
上圖中A爲三次握手,B爲數據傳輸,C爲四次揮手。下面咱們詳細介紹一下這三個部分。
首先咱們先圖解一下wireshark抓到的數據,以下圖:
咱們把這個過程分爲三部分,第一部分爲三次握手創建鏈接,第二部分爲數據傳輸,第三次爲四次揮手斷開鏈接。
三次握手
咱們分析一下三次握手的過程(包括ack 和 seq的值變化),
爲了方便描述咱們將主動發起請求的172.16.17.94:8080 主機稱爲客戶端,將返回數據的主機172.16.17.94:8080稱爲服務器,如下也是。第一次握手: 創建鏈接。客戶端發送鏈接請求,發送SYN報文,將seq設置爲0。而後,客戶端進入SYN_SEND狀態,等待服務器的確認。
第二次握手: 服務器收到客戶端的SYN報文段。須要對這個SYN報文段進行確認,發送ACK報文,將ack設置爲1。同時,本身還要發送SYN請求信息,將seq爲0。服務器端將上述全部信息一併發送給客戶端,此時服務器進入SYN_RECV狀態。
第三次握手: 客戶端收到服務器的ACK和SYN報文後,進行確認,而後將ack設置爲1,seq設置爲1,向服務器發送ACK報文段,這個報文段發送完畢之後,客戶端和服務器端都進入ESTABLISHED狀態,完成TCP三次握手。
數據傳輸
四次揮手
當客戶端和服務器經過三次握手創建了TCP鏈接之後,當數據傳送完畢,就要斷開TCP鏈接了,就有了神祕的「四次揮手」。
第一次揮手:客戶端向服務器發送一個FIN報文段,將設置seq爲160和ack爲112,;此時,客戶端進入 FIN_WAIT_1狀態,這表示客戶端沒有數據要發送服務器了,請求關閉鏈接;
第二次揮手:服務器收到了客戶端發送的FIN報文段,向客戶端回一個ACK報文段,ack設置爲1,seq設置爲112;服務器進入了CLOSE_WAIT狀態,客戶端收到服務器返回的ACK報文後,進入FIN_WAIT_2狀態;
第三次揮手:服務器會觀察本身是否還有數據沒有發送給客戶端,若是有,先把數據發送給客戶端,再發送FIN報文;若是沒有,那麼服務器直接發送FIN報文給客戶端。請求關閉鏈接,同時服務器進入LAST_ACK狀態;
第四次揮手:客戶端收到服務器發送的FIN報文段,向服務器發送ACK報文段,將seq設置爲161,將ack設置爲113,而後客戶端進入TIME_WAIT狀態;服務器收到客戶端的ACK報文段之後,就關閉鏈接;此時,客戶端等待2MSL後依然沒有收到回覆,則證實Server端已正常關閉,客戶端也能夠關閉鏈接了。
注意:在握手和揮手時確認號應該是對方序列號加1,傳輸數據時則是對方序列號加上對方攜帶應用層數據的長度。
應用層常見協議有HTTP、HTTPS 、FTP 、SMTP等。
TCP/IP模型咱們基本介紹完了,那層與層之間是怎樣合做和分工的呢,咱們用兩張圖介紹一下: 發送方的數據是從上往下傳輸的,即從應用層向物理層傳輸。接收方的數據是從下往上傳輸的,即從物理層嚮應用層傳輸。以下兩張圖。
發送方是從高層到低層封裝數據:
深刻理解TCP/IP模型就簡單介紹完了,若是有理解錯誤的地方,歡迎指正!