之前自己一個(gè)人負(fù)責(zé)完成了公司的消息推送服務(wù),和移動(dòng)端配合完成了掃碼登錄、訂單消息推送、活動(dòng)消息廣播等功能。為了加深自己對(duì)Websocket協(xié)議的理解,自己通過(guò)進(jìn)行抓包的方式學(xué)習(xí)了一番?,F(xiàn)在分享出來(lái),希望對(duì)大家能有所幫助。 Chrome控制臺(tái)(1)F12進(jìn)入控制臺(tái),點(diǎn)擊Network,選中ws欄,注意選中Filter。 (2)刷新頁(yè)面會(huì)得到一個(gè)ws鏈接。 (3)點(diǎn)擊鏈接可以查看鏈接詳情 注意紅框標(biāo)出的信息,后面會(huì)詳細(xì)說(shuō)明。 Fiddler:抓包調(diào)試?yán)?/h2>(1)打開(kāi)Fiddler,點(diǎn)開(kāi)菜單欄的Rules,選擇Customize Rules... (2)這時(shí)會(huì)打開(kāi)CustomRules.js文件,在class Handlers中加入以下代碼
(3)保存后就可以在Fiddler右邊欄的Log標(biāo)簽里,看到WebSocket的數(shù)據(jù)包 服務(wù)端發(fā)出的消息: 然后我們會(huì)發(fā)現(xiàn)每次會(huì)話關(guān)閉都是由客戶端發(fā)起的: 相對(duì)于Chrome控制臺(tái)來(lái)說(shuō)Fiddler抓包更加詳細(xì)一些,能知道會(huì)話消息是由客戶端還是服務(wù)端發(fā)出并且能知道消息類型。但是這仍然滿足不了深入理解學(xué)習(xí)Websocket協(xié)議的目的。如果是處理HTTP、HTTPS,還是用Fiddler。其他協(xié)議比如TCP,UDP 就用WireShark。TPC/IP協(xié)議是傳輸層協(xié)議,主要解決數(shù)據(jù)如何在網(wǎng)絡(luò)中傳輸,而HTTP、Websocket是應(yīng)用層協(xié)議,主要解決如何包裝數(shù)據(jù)。因?yàn)閼?yīng)用層是在傳輸層的基礎(chǔ)上包裝數(shù)據(jù),所以我們還是從底層開(kāi)始了解Websocket到底是個(gè)啥?是如何工作的? WireSharkWireShark(前稱Ethereal)是一個(gè)網(wǎng)絡(luò)封包分析軟件。網(wǎng)絡(luò)封包分析軟件的功能是擷取網(wǎng)絡(luò)封包,并盡可能顯示出最為詳細(xì)的網(wǎng)絡(luò)封包資料。WireShark抓包是根據(jù)TCP/IP五層協(xié)議來(lái)的,也就是物理層、數(shù)據(jù)鏈路層、網(wǎng)絡(luò)層、傳輸層、應(yīng)用層。我們主要關(guān)注傳輸層和應(yīng)用層。 TCP三次握手我們都知道,TCP建立連接時(shí),會(huì)有三次握手過(guò)程。下圖是WireShark截獲到的三次握手的三個(gè)數(shù)據(jù)包(雖然叫數(shù)據(jù)包,但是三次握手包是沒(méi)有數(shù)據(jù)的)。 點(diǎn)擊上圖中的數(shù)據(jù)包就可以查看每個(gè)數(shù)據(jù)包的詳情,這里我們需要明確幾個(gè)概念才能看懂每個(gè)數(shù)據(jù)包代表啥意義:
可以看到我們打開(kāi)的Transmission Control Protocol即為傳輸層(Tcp)
服務(wù)器收到客戶端發(fā)過(guò)來(lái)的TCP報(bào)文,由SYN=1知道客戶端要求建立聯(lián)機(jī),向客戶端發(fā)送一個(gè)SYN=1,ACK=1的TCP報(bào)文,將確認(rèn)序號(hào)設(shè)置為客戶端的序列號(hào)加1。
客戶端接收到服務(wù)器發(fā)過(guò)來(lái)的包后檢查確認(rèn)序列號(hào)是否正確,即第一次發(fā)送的序號(hào)+1,以及標(biāo)志位ACK是否為1。若正確則再次發(fā)送確認(rèn)包,ACK標(biāo)志為1。鏈接建立成功,可以發(fā)送數(shù)據(jù)了。 一次特殊的HTTP請(qǐng)求緊接著是一次Http請(qǐng)求(第四個(gè)包),說(shuō)明Http的確是使用Tcp建立連接的。 先來(lái)看傳輸層(Tcp): PSH(推送比特)置1,ACK置1,PSH置1說(shuō)明開(kāi)始發(fā)送數(shù)據(jù),同時(shí)發(fā)送數(shù)據(jù)ACK要置1,因?yàn)樾枰邮盏竭@個(gè)數(shù)據(jù)包的端給予確認(rèn)。PSH為1的情況,一般只出現(xiàn)在 DATA內(nèi)容不為0的包中,也就是說(shuō)PSH為1表示的是有真正的TCP數(shù)據(jù)包內(nèi)容被傳遞。 再來(lái)看應(yīng)用層(Http):這是一次特殊的Http請(qǐng)求,為什么是一次特殊的Http請(qǐng)求呢?Http請(qǐng)求頭中Connection:Upgrade Upgrade:websocket,Upgrade代表升級(jí)到較新的Http協(xié)議或者切換到不同的協(xié)議。很明顯WebSocket使用此機(jī)制以兼容的方式與HTTP服務(wù)器建立連接。WebSocket協(xié)議有兩個(gè)部分:握手建立升級(jí)后的連接,然后進(jìn)行實(shí)際的數(shù)據(jù)傳輸。首先,客戶端通過(guò)使用Upgrade: WebSocket和Connection: Upgrade頭部以及一些特定于協(xié)議的頭來(lái)請(qǐng)求WebSocket連接,以建立正在使用的版本并設(shè)置握手。服務(wù)器,如果它支持協(xié)議,回復(fù)與相同Upgrade: WebSocket和Connection: Upgrade標(biāo)題,并完成握手。握手完成后,數(shù)據(jù)傳輸開(kāi)始。這些信息在前面的Chrome控制臺(tái)中也可以看到。 請(qǐng)求: 響應(yīng): 由此我們可以總結(jié)出: Websocket的世界通信協(xié)議格式是WebSocket格式,服務(wù)器端采用Tcp Socket方式接收數(shù)據(jù),進(jìn)行解析,協(xié)議格式如下: 首先我們需要知道數(shù)據(jù)在物理層,數(shù)據(jù)鏈路層是以二進(jìn)制進(jìn)行傳遞的,而在應(yīng)用層是以16進(jìn)制字節(jié)流進(jìn)行傳輸?shù)摹?/p> 第一個(gè)字節(jié): FIN:1位,用于描述消息是否結(jié)束,如果為1則該消息為消息尾部,如果為零則還有后續(xù)數(shù)據(jù)包; Webdocket數(shù)據(jù)幀中OPCODE定義: 第二個(gè)字節(jié): MASK:1位,用于標(biāo)識(shí)PayloadData是否經(jīng)過(guò)掩碼處理,客戶端發(fā)出的數(shù)據(jù)幀需要進(jìn)行掩碼處理,所以此位是1。數(shù)據(jù)需要解碼。 上圖是客戶端發(fā)送給服務(wù)端的數(shù)據(jù)包,其中PayloadData的長(zhǎng)度為二進(jìn)制:01111110——>十進(jìn)制:126;如果值是126,則后面2個(gè)字節(jié)形成的16位無(wú)符號(hào)整型數(shù)的值是payload的真實(shí)長(zhǎng)度。也就是圈紅的十六進(jìn)制:00C1——>十進(jìn)制:193 byte。所以PayloadData的真實(shí)數(shù)據(jù)長(zhǎng)度是193 bytes; 根據(jù)我們的分析,客戶端到服務(wù)端數(shù)據(jù)包的websocket幀圖應(yīng)該為: 我們?cè)賮?lái)抓包分析一下服務(wù)器到客戶端的數(shù)據(jù)包: 可以發(fā)現(xiàn)服務(wù)器發(fā)送給客戶端的數(shù)據(jù)包中第二個(gè)字節(jié)中MASK位為0,這說(shuō)明服務(wù)器發(fā)送的數(shù)據(jù)幀未經(jīng)過(guò)掩碼處理,這個(gè)我們從客戶端和服務(wù)端的數(shù)據(jù)包截圖中也可以發(fā)現(xiàn),客戶端的數(shù)據(jù)被加密處理,而服務(wù)端的數(shù)據(jù)則沒(méi)有。(如果服務(wù)器收到客戶端發(fā)送的未經(jīng)掩碼處理的數(shù)據(jù)包,則會(huì)自動(dòng)斷開(kāi)連接;反之,如果客戶端收到了服務(wù)端發(fā)送的經(jīng)過(guò)掩碼處理的數(shù)據(jù)包,也會(huì)自動(dòng)斷開(kāi)連接)。 掩碼處理: 未掩碼處理: 根據(jù)我們的分析,服務(wù)端到客戶端數(shù)據(jù)包的websocket幀圖應(yīng)該為: TCP KeepAlive如上圖所示,TCP?;顖?bào)文總是成對(duì)出現(xiàn),包括TCP保活探測(cè)報(bào)文和TCP?;钐綔y(cè)確認(rèn)報(bào)文。 TCP?;钐綔y(cè)確認(rèn)報(bào)文就是對(duì)保活探測(cè)報(bào)文的確認(rèn),其報(bào)文格式如下: 因?yàn)閃ebsocket通過(guò)Tcp Socket方式工作,現(xiàn)在考慮一個(gè)問(wèn)題,在一次長(zhǎng)連接中,服務(wù)器怎么知道消息的順序呢?這就涉及到tcp的序列號(hào)(Sequence Number)和確認(rèn)號(hào)(Acknowledgment Number)。我的理解是序列號(hào)是發(fā)送的數(shù)據(jù)長(zhǎng)度;確認(rèn)號(hào)是接收的數(shù)據(jù)長(zhǎng)度。這樣講比較抽象,我們從TCP三次握手開(kāi)始(結(jié)合下圖)詳細(xì)分析一下。 包1: 總結(jié): |
|