【nodejs】全網(wǎng)首發(fā)教程 從零寫一個websocket服務(wù)器 無任何框架
前言
我寫的源碼只有200行,已經(jīng)足夠完成websocket服務(wù)器的基礎(chǔ)功能了。無論是自己添加功能,排查問題的便利度還是性能方面,都一定是比主流框架強的。學(xué)習(xí)也好,自己的小項目用也好,我的代碼是不二之選??梢灾苯邮褂胣pm i iiws來安裝。注意如果要修改源碼的話記得在package.json中把main把ws.min.js改成ws.js。
源碼放這里了: https://github.com/Bylx666/iiws,但用的英文注釋。也歡迎關(guān)注我的github
簡單說一下這個怎么用
理論知識
websocket不同于http,只有頭和內(nèi)容。websocket的通訊要作為“幀”來發(fā)送,而幀都是二進制的,相對來說服務(wù)器端處理會相對麻煩。
一個“幀”的基本格式如下
無論是向服務(wù)器發(fā)送還是服務(wù)器向客戶端發(fā)送都是需要發(fā)送幀形式的。第一次接觸二進制處理的話會很懵,我簡單說幾個概念:1 byte = 8 bits,bit只有1和0。buffer[n]取得的都是1byte, 也就是8個bit。上表的數(shù)字代表的都是bit,也就是一行是32 bits, 4 bytes。
上表中fin為1代表消息結(jié)束,0代表這是個片段幀。0的話需要先把這一幀的內(nèi)容加到上一個fin為0的內(nèi)容后面,直到出現(xiàn)fin為1的幀,代表了這個消息的結(jié)束。原生api中只提供了"data"接口,這個api只會給你散落的data信息,并不能把客戶端發(fā)送的消息完完整整的直接給你,就需要我們自己去處理。
opcode是operation code,就是操作碼。
二進制幀用的少,源碼中未涉及。一般使用json+base64傳輸二進制內(nèi)容。之所以opcode占4位是因為0xF(16進制的f)=1111(2進制),所以說一個byte可以容納2個16進制數(shù)。
payload length意思是內(nèi)容的大小,在編程中一般叫做長度。這個設(shè)計就很有意思了。首先看這個7位的payload length,如果塞滿的話它就是1111111,也就是127。減一呢?1111110,也就是126。塞滿的話意思就是就直接告訴你我要64位大小來塞這個消息的大小數(shù)值,126就是要16位。小于126的話就直接拿這7位來裝這個數(shù)字。
mask就是是否有掩碼。1有0無。注意一般客戶端是瀏覽器的話不要設(shè)置這個為1,規(guī)范中明確說了。
masking-key就是4 bytes的掩碼鍵,沒那么復(fù)雜,一行就能搞定(等會看代碼)。如果mask是0就是沒有掩碼鍵后面直接是內(nèi)容。
payload就是內(nèi)容,不多說。
代碼和思路
寫代碼第一步,造小輪子(明顯要用的框架)
但凡學(xué)過一點點js的都非常熟悉了,一筆帶過。
第二步,接入原生api。Websocket的本質(zhì)是http的upgrade。我們直接創(chuàng)建一個WSS類,更詳細的思路在代碼的注釋當中。
第三步,補全函數(shù)。上面代碼中很明顯用了非原生函數(shù),我們來跟著剛開始說的理論寫一下這些函數(shù)。
創(chuàng)建一幀
解析一幀的元數(shù)據(jù)
反掩碼(確實很簡單吧)
第四步,導(dǎo)出??
結(jié)語
自己學(xué)這東西的時候盯著別人的框架幾千行,費勁的理解,花了我很長時間。最后只用200行濃縮了最本質(zhì)的內(nèi)容時我也是很有成就感。這個教程可以說是我目前對websocket的所有理解,即使你并不是用nodejs編程,你也可以學(xué)到websocket通信的原理以及數(shù)據(jù)處理方式的思路。希望能對看到這的人有用,有哪里疑惑沒講明白的請在評論區(qū)指出。
