websocket与http都属于tcp/ip协议簇中的应用层协议,基于tcp协议,主要用于浏览器和服务器通信。
http是request-reply模式,只能由client先发数据;而websocket中,server可以主动发送数据给client。
http也是可以做长连接的, 只是一般不这么用;websocket一般用作长连接。
对于传输数据不大的情况下,http包头所占字节比较多,消息利用率不高,需要自定义协议。
自定义协议由两部分组成:
websocket就是解决这个问题的,websocket只定义了tcp包本身的信息,业务协议可以自己去定义,类似自定义协议。
微博即时聊天,qq、微信网页版即时聊天,比分网页版实时,股票行情,可以用websocket来做。
websocket,普遍的使用场景,用于服务器主动推送给浏览器, b/s模式的实时通信。websocket并不仅限于浏览器和服务器之间的实时通信。
websocket协议,参考rfc6455。
靠handshake来验证合法性
client发送的第一个包:
Upgrade
说明是websocket协议
Sec-WebSocket-Key
是用来进行验证的,具体方法如下:
// Sec-WebSocket-Key + GUID
str = "nwnCsQI3P/SqZ6I2dyyfFA==258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
sha = SHA1(str);
sec_websocket_accept = base64_encode(sha);
之后发送respose给client, 客户端对Sec_Websocket_Accept
进行验证。
handshake后,再发送的包就符合websocket协议。包分为两部分,一部分是header,另一部分是payload。http使用特殊字符\r\n
来界定包;而websocket则是在header中包含payload length
指定包的长度。具体协议参考rfc6455。
FIN: 1 bit
Indicates that this is the final fragment in a message. The first fragment MAY also be the final fragment.
Opcode: 4 bits
Defines the interpretation of the “Payload data”. If an unknown opcode is received, the receiving endpoint MUST Fail the WebSocket Connection. The following values are defined.
%x0 denotes a continuation frame
%x1 denotes a text frame
%x2 denotes a binary frame
%x3-7 are reserved for further non-control frames
%x8 denotes a connection close
%x9 denotes a ping
%xA denotes a pong
%xB-F are reserved for further control frames
0x8表示关闭连接。
Mask: 1 bit
Defines whether the “Payload data” is masked. If set to 1, a masking key is present in masking-key. All frames sent from client to server have this bit set to 1.
Payload length: 7 bits, 7+16 bits, or 7+64 bits
The length of the “Payload data”, in bytes: if 0-125, that is the payload length. If 126, the following 2 bytes interpreted as a 16-bit unsigned integer are the payload length. If 127, the following 8 bytes interpreted as a 64-bit unsigned integer (the most significant bit MUST be 0) are the payload length.
Masking-key: 0 or 4 bytes
All frames sent from the client to the server are masked by a 32-bit value that is contained within the frame. This field is present if the mask bit is set to 1 and is absent if the mask bit is set to 0.
mask = 0
,传明文
mask = 1
,传密文
如果mask=1
,则websocket的包头中就会有4个字节的masking-key
// transformed-octet-i = original-octet-i XOR masking-key-octet-j
j = i%4 // i MOD 4, masking-key是4个字节
payload[i] ^= masking_key[j]; // 发送端进行一次异或;接收端再次进行异或操作,得到原始内容
自定义协议为什么要进行close?
既然TCP有close操作,为什么websocket还要留一个opcode来断开?
这样做可以先在应用层把业务处理完成,然后再调用tcp的close,能做到更好的回收。
websocket的状态机,只有时间顺序,没有状态迁移。
handshake->tranmission->end
enum {
WS_HANDSHAKE = 0,
WS_TRANSMISSION = 1,
WS_END = 2,
};
tcp三次握手完成后,websocket协议还有一次握手。
websocket是一个应用层协议,主要用于服务器主动推送消息给浏览器。websocket要比http简单很多。