专栏/【nodejs】全网首发教程 从零写一个websocket服务器 无任何框架

【nodejs】全网首发教程 从零写一个websocket服务器 无任何框架

2023年03月10日 08:50--浏览 · --喜欢 · --评论
粉丝:512文章:10

前言

我写的源码只有200行,已经足够完成websocket服务器的基础功能了。无论是自己添加功能,排查问题的便利度还是性能方面,都一定是比主流框架强的。学习也好,自己的小项目用也好,我的代码是不二之选。可以直接使用npm i iiws来安装。注意如果要修改源码的话记得在package.json中把main把ws.min.js改成ws.js。

源码放这里了: https://github.com/Bylx666/iiws,但用的英文注释。也欢迎关注我的github

简单说一下这个怎么用


理论知识

websocket不同于http,只有头和内容。websocket的通讯要作为“帧”来发送,而帧都是二进制的,相对来说服务器端处理会相对麻烦。

一个“帧”的基本格式如下

无论是向服务器发送还是服务器向客户端发送都是需要发送帧形式的。第一次接触二进制处理的话会很懵,我简单说几个概念:1 byte = 8 bits,bit只有1和0。buffer[n]取得的都是1byte, 也就是8个bit。上表的数字代表的都是bit,也就是一行是32 bits, 4 bytes。

上表中fin为1代表消息结束,0代表这是个片段帧。0的话需要先把这一帧的内容加到上一个fin为0的内容后面,直到出现fin为1的帧,代表了这个消息的结束。原生api中只提供了"data"接口,这个api只会给你散落的data信息,并不能把客户端发送的消息完完整整的直接给你,就需要我们自己去处理。

opcode是operation code,就是操作码。

二进制帧用的少,源码中未涉及。一般使用json+base64传输二进制内容。之所以opcode占4位是因为0xF(16进制的f)=1111(2进制),所以说一个byte可以容纳2个16进制数。

payload length意思是内容的大小,在编程中一般叫做长度。这个设计就很有意思了。首先看这个7位的payload length,如果塞满的话它就是1111111,也就是127。减一呢?1111110,也就是126。塞满的话意思就是就直接告诉你我要64位大小来塞这个消息的大小数值,126就是要16位。小于126的话就直接拿这7位来装这个数字。

mask就是是否有掩码。1有0无。注意一般客户端是浏览器的话不要设置这个为1,规范中明确说了。

masking-key就是4 bytes的掩码键,没那么复杂,一行就能搞定(等会看代码)。如果mask是0就是没有掩码键后面直接是内容。

payload就是内容,不多说。

代码和思路

写代码第一步,造小轮子(明显要用的框架)

但凡学过一点点js的都非常熟悉了,一笔带过。

第二步,接入原生api。Websocket的本质是http的upgrade。我们直接创建一个WSS类,更详细的思路在代码的注释当中。

第三步,补全函数。上面代码中很明显用了非原生函数,我们来跟着刚开始说的理论写一下这些函数。

创建一帧

解析一帧的元数据

反掩码(确实很简单吧)

第四步,导出🥵

结语

自己学这东西的时候盯着别人的框架几千行,费劲的理解,花了我很长时间。最后只用200行浓缩了最本质的内容时我也是很有成就感。这个教程可以说是我目前对websocket的所有理解,即使你并不是用nodejs编程,你也可以学到websocket通信的原理以及数据处理方式的思路。希望能对看到这的人有用,有哪里疑惑没讲明白的请在评论区指出。

晚安


投诉或建议