webSocket学习总结

前言:

WebSocket protocol 是HTML5一种新的协议。它实现了浏览器与服务器全双工通信(full-duplex)。在这之前都是客户端主动请求服务端,一请求一应答,很多时候实现消息更新都是采用ajax轮询,有延迟,有了WebSocket双方都可以主动发给对端,实现真正的推送。

1、HTTP和webSocket

(1)HTTP协议有两种方式

  1. 短轮询:ajax请求定时轮询,浏览器请求,服务端响应
  2. 长轮询:浏览器请求到服务器,服务器一直打开,直到数据可发送。发送完数据后,浏览器关闭连接。

缺点:实时性低,服务端到浏览器反馈效率低。

(2)webSocket协议,一次HTTP握手后,脱离HTTP协议使用webSocket通信

(3)HTTP向webSocket如何改造?

2、webSocket分为两个部分(基于协议帧)

(1)握手 (handshake)

握手基于HTTP,版本至少:1.1,方法GET

client(客户端发起连接请求):

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。

server(服务端返回密钥):

服务端需要把密钥返回给客户端,完成握手,发送的数据格式如下:

至此,算是握手成功了!

HTTP/1.1 101 Switching Protocols Upgrade: websocket  // 指明使用websocket协议 Connection: Upgrade Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo= Sec-WebSocket-Protocol: chat

(2)数据传输(data transfer)

  1. 服务器端采用Tcp Socket方式接收数据,进行解析,协议格式如下:

  1. 第一个字节:

FIN:1位,用于描述消息是否结束,如果为1则该消息为消息尾部,如果为零则还有后续数据包;

RSV1,RSV2,RSV3:各1位,用于扩展定义的,如果没有扩展约定的情况则必须为0

OPCODE:4位,用于表示消息接收类型,如果接收到未知的opcode,接收端必须关闭连接。

Webdocket数据帧中OPCODE定义

0x0表示附加数据帧

0x1表示文本数据帧

0x2表示二进制数据帧

0x3-7暂时无定义,为以后的非控制帧保留

0x8表示连接关闭

0x9表示ping

0xA表示pong

0xB-F暂时无定义,为以后的控制帧保留

  1. 第二个字节

MASK:1位,用于标识PayloadData是否经过掩码处理,客户端发出的数据帧需要进行掩码处理,所以此位是1。数据需要解码。

PayloadData的长度:7位,7+16位,7+64位

如果其值在0-125,则是payload的真实长度。

如果值是126,则后面2个字节形成的16位无符号整型数的值是payload的真实长度。

如果值是127,则后面8个字节形成的64位无符号整型数的值是payload的真实长度。

上图是客户端发送给服务端的数据包,其中PayloadData的长度为二进制:01111110——>十进制:126;如果值是126,则后面2个字节形成的16位无符号整型数的值是payload的真实长度。也就是圈红的十六进制:00C1——>十进制:193 byte。所以PayloadData的真实数据长度是193 bytes;

3、webSocket实现接口:

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);
};

4、客户端和服务端实现流程:

5、demo演示:

git地址:https://github.com/yanghao001/springboot-service/tree/master/springboot-websocket

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值