Python?Web學習筆記之WebSocket?通信過程與實現(xiàn)

一、什么是 WebSocket ?

WebSocket 是一種標準協(xié)議滑沧,用于在客戶端和服務端之間進行雙向數據傳輸吨艇。但它跟 HTTP 沒什么關系躬它,它是基于 TCP 的一種獨立實現(xiàn)。

以前客戶端想知道服務端的處理進度东涡,要不停地使用 Ajax 進行輪詢冯吓,讓瀏覽器隔個幾秒就向服務器發(fā)一次請求,這對服務器壓力較大疮跑。另外一種輪詢就是采用 long poll 的方式组贺,這就跟打電話差不多,沒收到消息就一直不掛電話祖娘,也就是說锣披,客戶端發(fā)起連接后,如果沒消息贿条,就一直不返回 Response 給客戶端雹仿,連接階段一直是阻塞的。

而 WebSocket 解決了 HTTP 的這幾個難題整以。當服務器完成協(xié)議升級后( HTTP -> WebSocket )胧辽,服務端可以主動推送信息給客戶端,解決了輪詢造成的同步延遲問題公黑。由于 WebSocket 只需要一次 HTTP 握手邑商,服務端就能一直與客戶端保持通信摄咆,直到關閉連接,這樣就解決了服務器需要反復解析 HTTP 協(xié)議人断,減少了資源的開銷吭从。

隨著新標準的推進,WebSocket 已經比較成熟了恶迈,并且各個主流瀏覽器對 WebSocket 的支持情況比較好(不兼容低版本 IE涩金,IE 10 以下),有空可以看看暇仲。


使用 WebSocket 的時候步做,前端使用是比較規(guī)范的,js 支持 ws 協(xié)議奈附,感覺類似于一個輕度封裝的 Socket 協(xié)議全度,只是以前需要自己維護 Socket 的連接,現(xiàn)在能夠以比較標準的方法來進行斥滤。

下面我們就結合上圖具體來聊一下 WebSocket 的通信過程将鸵。

二、建立連接

1. 客戶端請求報文 Header

客戶端請求報文

與傳統(tǒng) HTTP 報文不同的地方:

這兩行表示發(fā)起的是 WebSocket 協(xié)議佑颇。

Sec-WebSocket-Key 是由瀏覽器隨機生成的咨堤,提供基本的防護,防止惡意或者無意的連接漩符。

Sec-WebSocket-Version 表示 WebSocket 的版本一喘,最初 WebSocket 協(xié)議太多,不同廠商都有自己的協(xié)議版本嗜暴,不過現(xiàn)在已經定下來了凸克。如果服務端不支持該版本,需要返回一個 Sec-WebSocket-Versionheader闷沥,里面包含服務端支持的版本號萎战。

創(chuàng)建 WebSocket 對象:

ws 表示使用 WebSocket 協(xié)議,后面接地址及端口

完整的客戶端代碼:

2. 服務端響應報文 Header

首先我們來看看服務端的響應報文:


我們一行行來解釋:

首先舆逃,101 狀態(tài)碼表示服務器已經理解了客戶端的請求蚂维,并將通過 Upgrade 消息頭通知客戶端采用不同的協(xié)議來完成這個請求;

然后路狮, Sec-WebSocket-Accept 這個則是經過服務器確認虫啥,并且加密過后的 Sec-WebSocket-Key;

最后奄妨, Sec-WebSocket-Protocol 則是表示最終使用的協(xié)議涂籽。

Sec-WebSocket-Accept 的計算方法:

將 Sec-WebSocket-Key 跟 258EAFA5-E914-47DA-95CA-C5AB0DC85B11 拼接;

通過 SHA1 計算出摘要砸抛,并轉成 base64 字符串评雌。

注意: Sec-WebSocket-Key/ Sec-WebSocket-Accept 的換算树枫,只能帶來基本的保障,但連接是否安全景东、數據是否安全砂轻、客戶端 / 服務端是否合法的 ws 客戶端、ws 服務端斤吐,其實并沒有實際性的保證搔涝。

創(chuàng)建主線程,用于實現(xiàn)接受 WebSocket 建立請求:

3. 進行通信

a. 服務端解析 WebSocket 報文

Server 端接收到 Client 發(fā)來的報文需要進行解析

Client 包格式

1.FIN: 占 1bit

0:不是消息的最后一個分片

1:是消息的最后一個分片

2.RSV1, RSV2, RSV3:各占 1bit

一般情況下全為 0曲初。當客戶端体谒、服務端協(xié)商采用 WebSocket 擴展時杯聚,這三個標志位可以非 0臼婆,且值的含義由擴展進行定義。如果出現(xiàn)非零的值幌绍,且并沒有采用 WebSocket 擴展颁褂,連接出錯。

3.Opcode: 4bit

%x0:表示一個延續(xù)幀傀广。當 Opcode 為 0 時颁独,表示本次數據傳輸采用了數據分片,當前收到的數據幀為其中一個數據分片伪冰;

%x1:表示這是一個文本幀(text frame)誓酒;

%x2:表示這是一個二進制幀(binary frame);

%x3-7:保留的操作代碼贮聂,用于后續(xù)定義的非控制幀靠柑;

%x8:表示連接斷開;

%x9:表示這是一個心跳請求(ping)吓懈;

%xA:表示這是一個心跳響應(pong)歼冰;

%xB-F:保留的操作代碼,用于后續(xù)定義的控制幀耻警。

4.Mask: 1bit

表示是否要對數據載荷進行掩碼異或操作隔嫡。

0:否

1:是

5.Payload length: 7bit or (7 + 16)bit or (7 + 64)bit

表示數據載荷的長度。

0~126:數據的長度等于該值甘穿;

126:后續(xù) 2 個字節(jié)代表一個 16 位的無符號整數彪杉,該無符號整數的值為數據的長度姻几;

127:后續(xù) 8 個字節(jié)代表一個 64 位的無符號整數(最高位為 0),該無符號整數的值為數據的長度。

6.Masking-key: 0 or 4bytes

當 Mask 為 1戒幔,則攜帶了 4 字節(jié)的 Masking-key;

當 Mask 為 0,則沒有 Masking-key吝羞。

掩碼算法:按位做循環(huán)異或運算,先對該位的索引取模來獲得 Masking-key 中對應的值 x内颗,然后對該位與 x 做異或钧排,從而得到真實的 byte 數據。

注意:掩碼的作用并不是為了防止數據泄密均澳,而是為了防止早期版本的協(xié)議中存在的代理緩存污染攻擊(proxy cache poisoning attacks)等問題恨溜。

7.Payload Data: 載荷數據

解析 WebSocket 報文代碼如下:

b. 服務端發(fā)送 WebSocket 報文

返回時不攜帶掩碼,所以 Mask 位為 0找前,再按載荷數據的大小寫入長度糟袁,最后寫入載荷數據。

struct 模塊解析

按照給定的格式 fmt躺盛,把數據封裝成字符串 ( 實際上是類似于 C 結構體的字節(jié)流 )

struct 中支持的格式如下表:

為了同 C 語言中的結構體交換數據项戴,還要考慮有的 C 或 C++ 編譯器使用了字節(jié)對齊,通常是以 4 個字節(jié)為單位的 32 位系統(tǒng)槽惫,故而 struct 根據本地機器字節(jié)順序轉換周叮。可以用格式中的第一個字符來改變對齊方式界斜,定義如下:

發(fā)送 WebSocket 報文代碼如下

三仿耽、總結

沒有其他能像 WebSocket 一樣實現(xiàn)全雙工傳輸的技術了,迄今為止各薇,大部分開發(fā)者還是使用 Ajax 輪詢來實現(xiàn)项贺,但這是個不太優(yōu)雅的解決辦法,WebSocket 雖然用的人不多峭判,可能是因為協(xié)議剛出來的時候有安全性的問題以及兼容的瀏覽器比較少开缎,但現(xiàn)在都有解決。如果你有這些需求可以考慮使用 WebSocket:

多個用戶之間進行交互朝抖;

需要頻繁地向服務端請求更新數據啥箭。

比如彈幕、消息訂閱治宣、多玩家游戲急侥、協(xié)同編輯、股票基金實時報價侮邀、視頻會議坏怪、在線教育等需要高實時的場景。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末绊茧,一起剝皮案震驚了整個濱河市铝宵,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖鹏秋,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件尊蚁,死亡現(xiàn)場離奇詭異,居然都是意外死亡侣夷,警方通過查閱死者的電腦和手機横朋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來百拓,“玉大人琴锭,你說我怎么就攤上這事⊙么” “怎么了决帖?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蓖捶。 經常有香客問我地回,道長,這世上最難降的妖魔是什么腺阳? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任落君,我火速辦了婚禮穿香,結果婚禮上亭引,老公的妹妹穿的比我還像新娘。我一直安慰自己皮获,他們只是感情好焙蚓,可當我...
    茶點故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著洒宝,像睡著了一般购公。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上雁歌,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天宏浩,我揣著相機與錄音,去河邊找鬼靠瞎。 笑死比庄,一個胖子當著我的面吹牛,可吹牛的內容都是我干的乏盐。 我是一名探鬼主播佳窑,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼父能!你這毒婦竟也來了神凑?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤何吝,失蹤者是張志新(化名)和其女友劉穎溉委,沒想到半個月后鹃唯,有當地人在樹林里發(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡瓣喊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年俯渤,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片型宝。...
    茶點故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡八匠,死狀恐怖,靈堂內的尸體忽然破棺而出趴酣,到底是詐尸還是另有隱情梨树,我是刑警寧澤,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布岖寞,位于F島的核電站抡四,受9級特大地震影響,放射性物質發(fā)生泄漏仗谆。R本人自食惡果不足惜指巡,卻給世界環(huán)境...
    茶點故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望隶垮。 院中可真熱鬧藻雪,春花似錦、人聲如沸狸吞。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蹋偏。三九已至便斥,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間威始,已是汗流浹背枢纠。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留黎棠,地道東北人晋渺。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像葫掉,于是被迫代替她去往敵國和親些举。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,614評論 2 353

推薦閱讀更多精彩內容