成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

理清 HTTP 之下的 TCP 流程,讓你的 HTTP 水平更上一層

開發(fā) 前端
我們平時都是分析 HTTP 請求響應(yīng),TCP 對我們來說看不見摸不著的,理解的模模糊糊。所以今天我們用 WireShark 抓了下 TCP 的包,來理清了 TCP 和 HTTP 的關(guān)系。

大家都知道 HTTP 的底層是 TCP,但是可能僅限于知道,并不是真正理解它們的關(guān)系。

平時我們用 chrome devtools 的 Network 工具也只是能分析 HTTP 請求:

TCP 層的東西看不見摸不著的,所以對它的理解也模模糊糊。

那怎么能看到 TCP 層的數(shù)據(jù)包來理清 TCP 和 HTTP 的關(guān)系呢?

這里推薦一個抓包工具 WireShark,它能抓取 TCP 層的包:

今天我們就用它來抓包分析下 TCP 和 HTTP 吧!

首先,我們準備這樣一段服務(wù)端代碼:

const express = require('express')
const app = express()
app.get('/', function (req, res) {
res.setHeader('Connection', 'close')
res.end('hello world');
})
app.listen(4000)

用 express 起了一個服務(wù),監(jiān)聽 4000 端口,處理路徑為 / 的 get 請求,返回 hello world 的響應(yīng)體,并設(shè)置 Connection: close 的 header。

瀏覽器訪問下:

header 和 body 都符合預(yù)期。

那 TCP 層都做了什么呢?

我們用 WireShark 抓包分析下:

打開 WireShark 后會看到有個設(shè)置按鈕:

因為我們訪問的是 localhost: 4000,所以這里選擇本地回環(huán)地址那個虛擬網(wǎng)卡,并輸入抓包過濾條件為 port 4000:

點擊 start 開始錄制,然后刷新一下瀏覽器:

這樣就能看到抓到的 TCP 數(shù)據(jù)包:

我們一一分析下。

在分析之前需要了解一些 TCP 基礎(chǔ)知識:

TCP 的頭部是這樣的:

TCP 是從端口到端口的傳輸協(xié)議,所以開始是源端口和目的端口。

接下來是序列號(sequence number),表示當前包的序號,后面是確認的序列號(acknowledgment number),表示我收到了序號為 xxx 的包。

然后紅框標出的部分是 flags 標識位,通過 0、1 表示有沒有:

這里我們只會用到其中的 SYN、ACK、FIN:

  • SYN:請求建立一個連接(說明這是鏈接的開始)。
  • ACK:表示 ack number 是否是有效的。
  • FIN:表示本端要斷開鏈接了(說明這是鏈接的結(jié)束)。

有了這些,我們就知道怎么區(qū)分 TCP 鏈接的開始和結(jié)束了。

再看一下抓到的包:

有 SYN 標志位的是連接的開始,有 FIN 標志位的是連接的結(jié)束,所以我們分為 3 段來看:

首先是連接開始的部分:

大家聽過 TCP 的三次握手么?說的就是這個。

其中有一個端口是 4000,這個是服務(wù)的端口,那另一個端口 57454 明顯就是瀏覽器的端口。

首先是瀏覽器向服務(wù)器發(fā)送了一個 SYN 的 TCP 請求,表示希望建立連接,序列號 Seq 是 0。

嚴格來說,序列號的相對值是 0,絕對值是 2454579144。

然后服務(wù)器向瀏覽器發(fā)送了一個 SYN 的 TCP 請求,表示希望建立連接,ACK 是 1,代表現(xiàn)在的 ack number 是有效的:

這里 ack number 的相對值是 1,絕對值是 2454579145,不就是上個 TCP 數(shù)據(jù)包的 seq 加 1 么?

TCP 連接中就是通過返回 seq number + 1 作為 ack number 來確認收到的。

然后又返回了一個 seq number 給瀏覽器,相對值是 0, 絕對值是 2765691269。

瀏覽器收到后返回了一個 TCP 數(shù)據(jù)包給服務(wù)器,ack number 自然是 2765691270,代表收到了連接請求。

這樣瀏覽器和服務(wù)器各自向?qū)Ψ桨l(fā)送了 SYN 的建立連接請求,并且都收到了對方的確認,那么 TCP 連接就建立成功了。

這就是 TCP 三次握手的原理!

趁熱打鐵來看下四次揮手的部分:

瀏覽器向服務(wù)器發(fā)送了有 FIN 標志位的數(shù)據(jù)包,表示要斷開連接,然后服務(wù)端返回了 ACK 的包表示確認。

之后服務(wù)端發(fā)送了 FIN 標志位的數(shù)據(jù)包給瀏覽器,表示要斷開連接,瀏覽器也返回了 ACK 的包表示確認。

這樣就完成了四次揮手的過程。

當然,具體確認的還是靠 ack number = seq number + 1 來實現(xiàn)的,和上面的一樣,就不展開了:

我們通過抓包理清了 TCP 連接建立和連接的過程。

那么為什么握手是三次,揮手是四次呢?

因為揮手是一個 FIN,一個 ACK,一個 FIN + ACK,一個 ACK:

而握手是一個 SYN,一個 ACK + SYN,一個 ACK:

不過是因為握手時把 ACK 和 SYN 合并到一個數(shù)據(jù)包了而已。

那揮手時能合并成三次么?

不能!因為有兩個 ack number,怎么合并,沖突了,而握手時只有一個 ack number,自然可以合并。

接下來再來看下連接建立后的 http 請求和響應(yīng)吧:

其實一次 HTTP 請求響應(yīng)會有四個 TCP 數(shù)據(jù)包,其中兩個數(shù)據(jù)包與滑動窗口有關(guān),這里先不展開了。

我們就看下 HTTP 的那兩個包吧:

請求的 seq 是這樣的:

而響應(yīng)的 ack 是這樣的:

相對值是 ack number = seq number + 1 沒錯,但是絕對值不是:

絕對值 2454579855 = 2454579145 + 710,也就是 ack number = seq number + segment len。

這些細節(jié)暫時不用深究。

總之,我們知道了HTTP 的請求和響應(yīng)是通過序列號關(guān)聯(lián)在一起的。

就算同一個 TCP 鏈接并行發(fā)送多個 HTTP 的請求和響應(yīng),它們也能找到各自對應(yīng)的那個。就是通過這個 seq number 和 ack number。

這里為啥鏈接建立了發(fā)送了一個請求就斷掉了呢?

我刷新瀏覽器,請求了兩次,發(fā)現(xiàn)經(jīng)歷了兩次連接的建立、http 請求響應(yīng)、連接斷開:

這是因為我設(shè)置了 Connection:close 的 header,它的作用就是一次 http 請求響應(yīng)結(jié)束就斷開 TCP 鏈接。

我們改成 HTTP 1.1 支持的 keep-alive 試試:

設(shè)置 Connection 為 keep-alive,然后設(shè)置 keep-alive 的細節(jié)為 timeout 10 ,也就是 10s 后斷開。

重啟服務(wù)器,再刷新下瀏覽器試試:

可以看到在一個 TCP 連接內(nèi)發(fā)送了多次 http 請求響應(yīng)。(通過 SYN 開始,F(xiàn)IN 結(jié)束)

這就是 keep-alive 的作用。

細心的同學(xué)會發(fā)現(xiàn)只是瀏覽器向服務(wù)器發(fā)送了 FIN 數(shù)據(jù)包,服務(wù)器沒有發(fā)給瀏覽器 FIN 數(shù)據(jù)包。

這是因為 keep-alive 的 header 只是控制的瀏覽器的斷開連接的行為,服務(wù)器的斷開連接邏輯是獨立的。

這樣,我們就理清了 HTTP 在 TCP 層面的流程,連接的建立、斷開,請求響應(yīng),還有 keep-alive。

總結(jié)

我們平時都是分析 HTTP 請求響應(yīng),TCP 對我們來說看不見摸不著的,理解的模模糊糊。

所以今天我們用 WireShark 抓了下 TCP 的包,來理清了 TCP 和 HTTP 的關(guān)系。

TCP 是從一個端口到另一個端口的傳輸控制協(xié)議,TCP header 中有序列號 seq number、確認序列號 ack number,還有幾個標志位:

  • SYN 標志位代表請求建立連接
  • ACK 標志位代表當前確認序列號是有效的。
  • FIN 標志位代表請求斷開連接

然后我們抓了 localhost:4000 的包分析了下 HTTP 請求的 TCP 流程,理清了三次握手(SYN、SYN + ACK、ACK),四次揮手(FIN、ACK、FIN + ACK、ACK)的連接建立、斷開的流程。知道了為什么不能三次揮手(因為兩個 ACK 沖突了)

然后還理清了同一個 TCP 連接傳輸?shù)亩鄠€ HTTP 請求響應(yīng)式通過 seq number 和 ack number 來關(guān)聯(lián)的。

之后我們分別測試了 Connection:close 和 Connection:keep-alive 的情況,發(fā)現(xiàn)確實 keep-alive 能減少頻繁的連接建立和斷開,能復(fù)用同一個 TCP 鏈接。

HTTP 是通過 TCP 完成端口到端口的數(shù)據(jù)傳輸?shù)摹R粋€ TCP 連接可以傳輸多個 HTTP 請求、響應(yīng)。請求和響應(yīng)的關(guān)聯(lián)是通過 TCP 包的序列號 seq。

理清了 TCP 和 HTTP 的關(guān)系,你是否對 HTTP 的理解更深了呢?

責(zé)任編輯:姜華 來源: 神光的編程秘籍
相關(guān)推薦

2014-08-18 14:54:54

Git

2023-09-24 23:07:24

流量抑制風(fēng)暴控制

2020-03-01 18:00:00

人工智能AI環(huán)保

2023-11-01 13:34:37

Python

2023-02-28 13:19:59

冗余代碼Ftp

2011-03-31 09:51:45

Windows XP

2012-05-28 14:18:33

Web

2021-01-21 11:24:16

智能安全首席信息安全官CISO

2011-03-31 09:57:54

Windows XP

2017-07-27 08:38:51

JavaLinux

2023-07-21 08:01:13

CSSInherit?

2025-01-20 00:06:13

2023-07-04 08:33:46

Python對象編程

2024-04-09 09:02:06

Node.jsJavaScript單線程

2021-03-25 15:07:50

編程技術(shù)工具

2017-07-31 17:54:04

IT技術(shù)周刊

2022-09-29 10:26:59

iOSScaffoldflutter

2009-10-23 14:46:43

2019-12-24 09:05:08

框架薪資Web

2018-05-10 14:34:48

薪資Java開發(fā)
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 亚洲人成人一区二区在线观看 | 网站一区二区三区 | 欧美激情国产精品 | 亚洲精品成人av久久 | 国产精品日本一区二区在线播放 | 国产人久久人人人人爽 | 成人午夜视频在线观看 | 高清人人天天夜夜曰狠狠狠狠 | 亚州毛片| 亚洲va欧美va天堂v国产综合 | 欧美性网站 | 在线观看视频91 | 在线视频 欧美日韩 | 久久av网| 国产日韩精品视频 | 一区二区中文 | 一级毛片免费视频 | 美女操网站 | 国产高清一区二区三区 | av在线成人| 91精品国产综合久久久久久丝袜 | 欧州一区二区三区 | 成人网址在线观看 | 成人av在线播放 | 国产99久久久国产精品下药 | 成人精品鲁一区一区二区 | 久久国产精品亚洲 | 欧美日韩在线视频一区 | 精品国产视频在线观看 | a毛片| 国产一区免费 | av一级 | 成人国产在线视频 | 欧美色a v | 尤物在线 | 成人福利视频 | 国产激情视频在线观看 | 殴美一级片 | 成人高清在线 | 91精品国产综合久久久久久 | 日韩和的一区二区 |