(二)gof websocket消息處理

本項(xiàng)目地址:gof 一個(gè)支持百萬連接的websocket框架
本文提及的內(nèi)容包含在:conn.go
上一章節(jié)中,我們創(chuàng)建了一個(gè)epoll結(jié)構(gòu)體,并在該結(jié)構(gòu)體中記錄了一個(gè)epoll對(duì)象。接下來我們就需要通過初始化該對(duì)象,從而實(shí)現(xiàn)消息的接收。

一、WebSocket的流程

首先,websocket也是作用在tcp連接之上的。因此,websocket的工作過程如下:

1、三次握手

這個(gè)過程是在Tcp層完成的。而我們的gof是應(yīng)用層,所以這份工作,linux底層 已經(jīng)幫我們完成了。

2、發(fā)送header頭

握手完成之后,會(huì)在服務(wù)端建立一個(gè)socket句柄,首先接收到的消息就是客戶端發(fā)送的header頭信息。其中包含一下幾個(gè)內(nèi)容:

Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cache-Control: no-cache
Connection: Upgrade
Host: 127.0.0.1:8801
Origin: http://www.easyswoole.com
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
Sec-WebSocket-Key: qHHCi/x3CScAZASynxuiJA==
Sec-WebSocket-Version: 13
Upgrade: websocket

3、服務(wù)端回應(yīng)消息頭

服務(wù)端在收到消息頭之后需要對(duì)客戶端進(jìn)行回應(yīng),其中必須要包含的內(nèi)容為:

Connection: Upgrade
Sec-WebSocket-Accept: SzZpB9M8fiQtfbE4F1iAthSkY9k=
Sec-WebSocket-Extensions: permessage-deflate
Upgrade: websocket

在完成了這些工作之后,客戶端和服務(wù)端就可以進(jìn)行通信了。

二、websocket消息幀

在完成了握手和消息頭的回應(yīng)之后,websocket收發(fā)消息是通過消息幀來進(jìn)行的。結(jié)構(gòu)如下:

0                   1                   2                   3
  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 +-+-+-+-+-------+-+-------------+-------------------------------+
 |F|R|R|R| opcode|M| Payload len |    Extended payload length    |
 |I|S|S|S|  (4)  |A|     (7)     |             (16/64)           |
 |N|V|V|V|       |S|             |   (if payload len==126/127)   |
 | |1|2|3|       |K|             |                               |
 +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
 |     Extended payload length continued, if payload len == 127  |
 + - - - - - - - - - - - - - - - +-------------------------------+
 |                               |Masking-key, if MASK set to 1  |
 +-------------------------------+-------------------------------+
 | Masking-key (continued)       |          Payload Data         |
 +-------------------------------- - - - - - - - - - - - - - - - +
 :                     Payload Data continued ...                :
 + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
 |                     Payload Data continued ...                |
 +---------------------------------------------------------------+

對(duì)于消息幀的解釋,在這里參考知乎的一篇文章:websocket 協(xié)議幀 解析
FIN:1 bit
表示這是不是消息的最后一幀。 %x0:還有后續(xù)幀 %x1:最后一幀
RSV1、RSV2、RSV3:1 bit
擴(kuò)展字段,除非一個(gè)擴(kuò)展經(jīng)過協(xié)商賦予了非零值的某種含義,否則必須為0
opcode:4 bit
解釋 payload data 的類型,如果收到識(shí)別不了的opcode,直接斷開。分類值如下: %x0:連續(xù)的幀 %x1:text幀 %x2:binary幀 %x3 - 7:為非控制幀而預(yù)留的 %x8:關(guān)閉握手幀 %x9:ping幀 %xA:pong幀 %xB - F:為非控制幀而預(yù)留的
MASK:1 bit
標(biāo)識(shí) Payload data 是否經(jīng)過掩碼處理,如果是 1,Masking-key域的數(shù)據(jù)即為掩碼密鑰,用于解碼Payload data。協(xié)議規(guī)定客戶端數(shù)據(jù)需要進(jìn)行掩碼處理,所以此位為1
Payload len:7 bit | 7+16 bit | 7+64 bit
表示了 “有效負(fù)荷數(shù)據(jù) Payload data”,以字節(jié)為單位: - 如果是 0~125,那么就直接表示了 payload 長度 - 如果是 126,那么 先存儲(chǔ) 0x7E(=126)接下來的兩個(gè)字節(jié)表示的 16位無符號(hào)整型數(shù)的值就是 payload 長度 - 如果是 127,那么 先存儲(chǔ) 0x7E(=126)接下來的八個(gè)字節(jié)表示的 64位無符號(hào)整型數(shù)的值就是 payload 長度
Masking-key:0 | 4 bytes
掩碼密鑰,所有從客戶端發(fā)送到服務(wù)端的幀都包含一個(gè) 32bits 的掩碼(如果mask被設(shè)置成1),否則為0。一旦掩碼被設(shè)置,所有接收到的 payload data 都必須與該值以一種算法做異或運(yùn)算來獲取真實(shí)值。
ws協(xié)議中,數(shù)據(jù)掩碼的作用是增強(qiáng)協(xié)議的安全性。但數(shù)據(jù)掩碼并不是為了保護(hù)數(shù)據(jù)本身,因?yàn)樗惴ū旧硎枪_的,運(yùn)算也不復(fù)雜。除了加密通道本身,似乎沒有太多有效的保護(hù)通信安全的辦法,那么為什么還要引入掩碼計(jì)算呢,除了增加計(jì)算機(jī)器的運(yùn)算量外似乎并沒有太多的收益(這也是不少同學(xué)疑惑的點(diǎn))
答案還是兩個(gè)字:安全。但并不是為了防止數(shù)據(jù)泄密,而是為了防止早期版本的協(xié)議中存在的代理緩存污染攻擊(proxy cache poisoning attacks)等問題
Payload data:(x+y) bytes
它是 Extension data 和 Application data 數(shù)據(jù)的總和,但是一般擴(kuò)展數(shù)據(jù)為空。
Extension data:x bytes
除非擴(kuò)展被定義,否則就是0
Application data:y bytes
占據(jù) Extension data 后面的所有空間

在下一章節(jié)中,我們就通過實(shí)際的代碼來對(duì)于websocket的發(fā)送數(shù)據(jù)和接收數(shù)據(jù)進(jìn)行詳細(xì)的說明。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Websocket 協(xié)議格式說明 最近整理項(xiàng)目中關(guān)于websocket中的部分,由于之前代碼中websocket的...
    Lucas汪星人閱讀 898評(píng)論 0 0
  • 前言 公司項(xiàng)目使用WebSocket作為主要的請(qǐng)求方式,知其然也要知其所以然,會(huì)用也需要知道它的基本原理,所以寫此...
    madaoCN閱讀 1,182評(píng)論 0 2
  • <!DOCTYPE html> 查看源 window.WRM=window.WRM||{};window....
    SMSM閱讀 927評(píng)論 1 0
  • 轉(zhuǎn)載自公眾號(hào):FightingCoder WebSocket 協(xié)議和知識(shí) WebSocket是一種在單個(gè)TCP連接...
    蒼簡閱讀 4,247評(píng)論 2 11
  • 夜鶯2517閱讀 128,215評(píng)論 1 9

友情鏈接更多精彩內(nèi)容