透過QUIC協議,來看看怎麼學習網路協議
這篇文章帶大家了解QUIC協議,並以QUIC協議為例,來聊聊如何學習網路協議,希望對大家有幫助!
在先前發布的關於 s2n-quic 的文章中,有讀者問我如何學習像 QUIC 這樣的網路協定。對於大部分網路從業者來說,雖然大家每天都在跟網路打交道,但很少有人會(需要)關心HTTP 之下的網路協定的細節,大部分時候,了解個大概,知道如何使用就可以了。如果你對QUIC 一點概念都沒有,那麼,下面這個圖能幫助你很好地了解QUIC 在HTTP/3 生態中的地位:
那麼,如果你就是要詳盡地了解QUIC 的知識,該如何入手呢?
作為一個曾經的網路協定和網路設備的開發者,我自己的心得是:從 RFC 入手,輔以 wireshark 抓包,來快速掌握目標協定。
對於 QUIC 而言,我們首先需要閱讀的是 RFC9000。協議的閱讀是非常枯燥的事情,需要一定的耐心,如果英文不太好,可以用 google translate 將其翻譯成中文,快速瀏覽一番(泛讀)。第一遍閱讀主要了解裡面的主要概念,以及主要流程。
之後,我們就可以撰寫使用 QUIC 協議的程序,然後透過 wireshark 抓包,透過研究實際的報文,對比 RFC 協議中的內容(精讀),來更深入地理解協議的本質。
我們還是以上一篇文章中的程式碼為基礎,建構 echo 用戶端和伺服器。為方便大家閱讀,我把程式碼也貼上來。有興趣的同學可以自行 clone 我的 repo,並執行 client/server 程式碼。
客戶端程式碼(請參閱github: tyrchen/rust-training/live_coding/quic-test/examples/client.rs):
#服務端程式碼(見github: tyrchen/rust-training/live_coding/quic-test/examples/server.rs):
這兩段程式碼建構了一個最簡單的echo server。我們可以使用 wireshark 監聽本地 loopback 介面下的 UDP 包,進行抓包。要注意的是,對於 QUIC 這樣使用了 TLS 協定的流量,即便抓到了包,可能只有頭幾個包可讀,後續的包都是加密內容,無法閱讀。因此,我們在建置 client/server 時,需要想辦法把伺服器和客戶端之間協商出來的 session key 抓取下來,供 wireshark 解密使用。一般 SSL/TLS 函式庫都會提供這個功能。例如對於 Rustls,我們可以在 tls config 中使用 key_log。如果你仔細看上面server 的程式碼,你會看到這句話:
let config = Builder::new() .with_certificate(CERT_PEM, KEY_PEM)? .with_key_logging()? # 使能 keylogging .build()?;
使用了key_log 後,在啟動server 的時候,我們只需要指定SSLKEYLOGFILE 就可以了:
SSLKEYLOGFILE=session.log cargo run --example server
在抓包完成後,打開wireshark 的preference,選擇TLS 協議,把log 的路徑放進去就可以了:
以下是一次完整的客戶端和伺服器的交互的抓包,我們看到,所有「protected payload」 都被正常顯示出來了:
#因為我們的echo client 只做了最簡單的動作(只開了一個bidirectional stream),所以透過這個抓包,我們專注於可以研究QUIC 協定建立連線的過程。
客戶端發送的首包
我們看客戶端發送的第一個訊息:
#這個報文包含了非常豐富的資訊。首先,和TCP 握手不同的是,QUIC 的首包非常大,有1200 字節之多(協議要求UDP payload at least 1200 bytes),包含QUIC 頭,一個255 字節的CRYPTO frame,以及890 字節PADDING frame。從 header 可以看到,這個 QUIC 套件的型別是 Initial。
QUIC 封包類型
#對於QUIC 套件來說,Header 是明文,之後的所有frame payload 都是密文(除了頭幾個包)。我們看到這個首包是一個 Long Header 報文,在 RFC9000 的 17.2 節中,定義了 Long Header Packet:
Long Header Packet { Header Form (1) = 1, Fixed Bit (1) = 1, Long Packet Type (2), Type-Specific Bits (4), Version (32), Destination Connection ID Length (8), Destination Connection ID (0..160), Source Connection ID Length (8), Source Connection ID (0..160), Type-Specific Payload (..), }
感興趣的可以自行去閱讀 RFC 相應的章節。對於 Long Header 報文,有以下幾種類型:
既然有 Long Header packet,那么就有 Short Header packet,Short Header packet 目前的版本只有一种:
1-RTT Packet { Header Form (1) = 0, Fixed Bit (1) = 1, Spin Bit (1), Reserved Bits (2), Key Phase (1), Packet Number Length (2), Destination Connection ID (0..160), Packet Number (8..32), Packet Payload (8..), }
为什么需要 connection id?
在我们捕获的这个报文头中,我们看到有 Source Connection ID(SCID)和 Destination Connection ID(DCID)这个新的概念。你也许会好奇:QUIC 不是基于 UDP/IP 的协议么?底层的协议已经有五元组(src ip / src port / dst ip / dst port / protocol)来描述一个连接(connection),为什么还需要 connection id 这样一个新的概念?
这是为了适应越来越多的移动场景。有了 QUIC 层自己的 connection id,底层网络(UDP/IP)的变化,并不会引发 QUIC 连接的中断,也就是说,你从家里开车出门,即便手机的网络从 WIFI(固网运营商分配给你的 IP)切换到蜂窝网络(移动运营商分配给你的 IP),整个 UDP/IP 网络变化了,但你的 QUIC 应用只会感受到细微的延迟,并不需要重新建立 QUIC 连接。
从这个使用场景来看,QUIC 底层使用无连接的 UDP 是非常必要的。
首包中就包含了 TLS hello?
我们接下来看看 CRYPTO frame:
可以看到,QUIC 在建立连接的首包就把 TLS Client Hello 囊括在 CRYPTO frame 中。并且使用的 TLS版本是 1.3。在 Client Hello 的 extension 中,QUIC 协议使用了一个 quic_transport_parameters 的 extension,用来协商 QUIC 自己的一些初始值,比如支持多少个 stream,这个连接中可以最多使用多少个 active connection id 等等。
QUIC 支持哪些 frame?
现在我们已经见到了两种 Frame:CRYPTO 和 PADDING。下表中罗列了 QUIC 所有支持的 frame:
服务器的回包
我们来看 server 的回包:
这里有一些新东西。首先,一个 UDP 包内部可以包含若干个 QUIC payload,我们看到 server 回复了一个 QUIC Initial 报文和一个 QUIC Handshake 报文。在 Initial 报文中,我们看到了一个 ACK frame,可见 QUIC 虽然构建于 UDP,但在 QUIC 协议内部构建了类似 TCP 的确认机制。
我们之前看到,在 Initial 报文的 CRYPTO frame 中,客户端发送了 TLS Client Hello,同样的,服务器在 Initial 报文的 CRYPTO frame 中发送了 TLS Server Hello。这个我们就略过不看。
在 Handshake 报文中:
服务器发送了自己的证书,并结束了 TLS handshake。
客户端结束 Handshake
我们再看第三个包,客户端发送给服务器结束 TLS 握手:
这个包依旧包含两个 QUIC 报文,其中第一个就是一个 ACK frame,来确认收到了服务器的 Server Hello 那个 QUIC 报文;第二个包含一个 ACK frame,确认服务器的 Handshake,随后有一个 CRYPTO frame 结束客户端的 TLS handshake。
TLS 握手结束之后,客户端和服务器就开始应用层的数据交换,此刻,所有数据都是加密的。
客户端发送一个 “hello” 文本
在我们的 echo client/server 代码中,客户端连接到服务器后,就可以等待用户在 stdin 的输入,然后将其发送到服务器。服务器收到客户端数据,原封不动发回,客户端再将其显示到 stdout 上。在这个过程的前后,客户端和服务器间有一些用于连接管理的 QUIC 报文,比如 PING。我们就略过,只看发送应用层数据的报文。下图是客户端发送的包含 “hello” 文本的报文:
可以看到,這裡 QUIC 訊息是個 Short Header packet,除了 ACK frame 外,它還有一個 STREAM frame。這個 stream 的 stream ID 最低兩位是 00,代表是客戶端發起的,雙向的 stream。由於使用了兩位來表達類型,所以QUIC 的stream 有以下類型:
我們來看STREAM frame 的length(6) 和Data(68 65 6c 6c 6f 0a )。 Data 裡的內容如果用 ASCII 表示,剛好是 “hello
伺服器回覆「hello」文字
#最後是伺服器echo back:
賢者時刻
相信透過上面對照著wireshark 抓包進行的QUIC 簡介,能讓你對QUIC 協議有一個初步的認識。上篇文章,我們說 QUIC 支援多路復用,並且解決了傳輸層隊頭阻塞的問題。透過這篇文章的介紹,你能回答以下兩個問題麼?- QUIC 透過哪個 frame 類型來做多路復用的?
- QUIC 如何解決傳輸層隊頭阻塞的?
以上是透過QUIC協議,來看看怎麼學習網路協議的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

vivo快充主要有兩個協議:1、「QC 2.0」快充協議,「QC2.0」就是「Quick Charge 2.0」技術,是高通公司發布的快充技術2.0版本,可以輸出5V、9V、12V 、20V四組電壓;2、PD快充協議,是由“USB-IF”組織制定的一種快速充電規範,是目前主流的快充協議之一,可以使目前默認最大功率“5V/2A”的“type-c”介面提高到100W。

pd3.0快充協定最高支援「100W」。 2015年11月,USB PD快充迎來了大版本更新,進入到了USB PD3.0快充時代;PD3.0協議支援5V3A、9V3A、12V3A、15V3A、20V5A輸出,最大功率可以到100W,不僅可以用在手機充電上,還可以用筆記本或是顯示器供電。

5種工業通訊協議:1、Modbus協議,是應用於電子控制器上的一種通用語言;2、RS-232協議,是一種串行物理接口標準;3、RS-485協議,是在RS232的基礎上發展來的;4、HART協議,是一種用於現場智慧儀表和控制室設備之間的通訊協議;5、MPI協議,是一個跨語言的通訊協議,用於編寫並行電腦。

近年來,Go語言作為一種高效、輕量級、並發性優異的程式語言,受到越來越多人的關注與喜愛。在網路程式設計方面,Go語言擁有豐富的網路協定支持,能夠幫助開發者快速、方便地建立網路應用。下面就讓我們來了解一下Go語言中的網路協定有哪些。 1.TCPTCP(TransmissionControlProtocol,傳輸控制協定)是一種在電腦網路中常用的傳輸協

Java網路程式設計中常用的協定包括:TCP/IP:用於可靠資料傳輸和連線管理。 HTTP:用於Web資料傳輸。 HTTPS:HTTP的安全版本,使用加密傳輸資料。 UDP:用於快速但不穩定的資料傳輸。 JDBC:用於與關聯式資料庫互動。

隨著互聯網技術的不斷發展,越來越多的企業級應用需要向其它應用程式提供介面以實現資料和業務的互動。在這種情況下,我們需要一種可靠的協定來傳輸資料並確保資料的完整性和安全性。 SOAP(SimpleObjectAccessProtocol)是一種基於XML的協議,可用於在Web環境中實現應用程式之間的通訊。而PHP作為一種流行的Web程式語言,

QC4+快充協定是USB PD PPS協定和QC3.0/2.0快充協定的綜合體,是一種多功能、多協定的快充技術。 QC4+充電協定對USB PD3.0(PPS)進行了相容,同時向下相容USB PD2.0、QC3.0、QC2.0、BC1.2等協定。支援USB PD、QC4+的首要前提,是兩端皆有USB-C介面的支援和基於USB-C介面中的CC(配置通道)的電力協商封包。

網路協議的三要素:1、語義,即解釋控制訊息每個部分的意義;它規定了需要發出何種控制訊息,以及完成的動作與做出什麼樣的回應。 2.語法,即使用者資料與控制資訊的結構與格式,以及資料出現的順序。 3、時序,即事件發生順序的詳細說明。
