WebSocket protocol 是HTML5一种新的协议。它实现了浏览器与服务器全双工通信(full-duplex)。在这之前都是客户端主动请求服务端,一请求一应答,很多时候实现消息更新都是采用ajax轮询,有延迟,有了WebSocket双方都可以主动发给对端,实现真正的推送。
(2)webSocket协议,一次HTTP握手后,脱离HTTP协议使用webSocket通信
Sec-Websocket-Key后面的那一串长度为24的字符串是客户端随机生成16位字符再通过base64编码生成的,我们暂时叫它cli_key。服务器必须用它经过一定的运算规则生成服务器端的key,暂时叫做ser_key,然后把ser_key发回给客户端,客户端验证正确后,握手成功。
GET /chat HTTP/1.1 Host: server.example.com Upgrade: websocket // 指明使用websocket协议 Connection: Upgrade Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== Origin: http://example.com Sec-WebSocket-Protocol: chat, superchat Sec-WebSocket-Version: 13 // 使用协议版本
然后把这一长串经过SHA-1算法加密,得到长度为20字节的二进制数据,
再将这些数据经过Base64编码,最终得到服务端的密钥,也就是ser_key。
服务端需要把密钥返回给客户端,完成握手,发送的数据格式如下:
HTTP/1.1 101 Switching Protocols Upgrade: websocket // 指明使用websocket协议 Connection: Upgrade Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo= Sec-WebSocket-Protocol: chat
FIN:1位,用于描述消息是否结束,如果为1则该消息为消息尾部,如果为零则还有后续数据包;
RSV1,RSV2,RSV3:各1位,用于扩展定义的,如果没有扩展约定的情况则必须为0
OPCODE:4位,用于表示消息接收类型,如果接收到未知的opcode,接收端必须关闭连接。
MASK:1位,用于标识PayloadData是否经过掩码处理,客户端发出的数据帧需要进行掩码处理,所以此位是1。数据需要解码。
如果值是126,则后面2个字节形成的16位无符号整型数的值是payload的真实长度。
如果值是127,则后面8个字节形成的64位无符号整型数的值是payload的真实长度。
上图是客户端发送给服务端的数据包,其中PayloadData的长度为二进制:01111110——>十进制:126;如果值是126,则后面2个字节形成的16位无符号整型数的值是payload的真实长度。也就是圈红的十六进制:00C1——>十进制:193 byte。所以PayloadData的真实数据长度是193 bytes;
interface WebSocket : EventTarget {
readonly attribute DOMString url;
// ready state
const unsigned short CONNECTING = 0;
const unsigned short OPEN = 1;
const unsigned short CLOSING = 2;
const unsigned short CLOSED = 3;
readonly attribute unsigned short readyState;
readonly attribute unsigned long bufferedAmount;
// networking
attribute EventHandler onopen;
attribute EventHandler onerror;
attribute EventHandler onclose;
readonly attribute DOMString extensions;
readonly attribute DOMString protocol;
void close([Clamp] optional unsigned short code, optional DOMString reason);
// messaging
attribute EventHandler onmessage;
attribute DOMString binaryType;
void send(DOMString data);
void send(Blob data);
void send(ArrayBuffer data);
void send(ArrayBufferView data);
};
git地址:https://github.com/yanghao001/springboot-service/tree/master/springboot-websocket