近来项目中使用websocket,于是来研究一番。websocket传输协议有两个部分,握手和数据传输
握手
GET / HTTP/1.1 HOST: <IP>:<PORT> Sec-Websocket-Version: 13 Sec-Websocket-Key: <KEY> Connection: keep-alive, Upgrade Upgrade: websocket
之后服务端会返回类似下面的数据
HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: <ACCEPT_KEY> Sec-WebSocket-Version: 13 Server: swoole-websocket-server
校检连接
这里可以对accept key进行校检,确定服务器确实是websocket服务器,校检算法为
sha1(KEY+‘258EAFA5-E914-47DA-95CA-C5AB0DC85B11’),将得到的一串字符串用16进制表示,之后再进行base64编码。
base64_encode(pack('H*', sha1(KEY.'258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));
发送数据
websocket数据使用帧序列传输
下面介绍的是这个数据包的含义。
FIN:长度1位,表示是否是最后一帧,为1则表示最后一帧,为0则表示还有后续帧
RSV(1-3):每一个1位,保留位。目前为0,如果服务端与客户端没有协商,那么非0则认为是一个错误的帧
opcode:表示帧格式,占4位,格式如下
0x00,表示继续帧 0x01,表示文本帧 0x02,表示二进制帧 0x03-0x07,保留的未定义非控制帧 0x08,连接关闭帧 0x09,表示ping 0xA,表示pong 0xB-0xF,用于保留的控制帧
MASK,1位,定义负载数据是否使用掩码,1为使用掩码,0为不使用掩码
Payload Length,7位,7+16位,7+64位,定义负载数据的长度,以字节为单位。这部分如果为0-125,则负载长度则就是这段定义的长度,如果为126,之后的 Extend payload Length 16位将作为负载长度,如果为127,那么之后的Extend payload Length 64位将作为负载长度。
负载数据长度为扩展数据长度+应用数据长度,扩展数据可以为0
Masking-key ,0 或者 32位,mask位设为0,则该字段缺失(不过协议要求,所有的帧都需要使用mask)
Payload data,负载数据=扩展数据+应用数据
Extension data,可以是客户端和服务端协商的长度,如果没有则为0
Application data,需要发送的真正的应用数据