WebSocket

WebSocket与HTTP的异同

HTTP只能由客户端发起,做不到服务器主动推送消息(单向请求)。当服务器有连续的状态变化的时候,客户端想要获知只能采用轮询的方式(效率低,浪费资源)。

当需要在浏览器做一个在线多人游戏的时候,浏览器通过JavaScript启动一个定时器,然后以固定的间隔给服务器发请求,询问服务器有没有新消息。这个机制的缺点一是实时性不够,二是频繁的请求会给服务器带来极大的压力。所以需要一个新的协议来建立无限制的全双工通信

连接

WebSocket利用了HTTP协议来建立连接。握手阶段采用 HTTP 协议

连接必须由浏览器发起,因为请求协议是一个标准的HTTP请求,格式如下:

1
2
3
4
5
6
7
GET ws://localhost:3000/ws/chat HTTP/1.1
Host: localhost
Upgrade: websocket
Connection: Upgrade
Origin: http://localhost:3000
Sec-WebSocket-Key: client-random-string
Sec-WebSocket-Version: 13
  1. GET请求的地址不是类似/path/,而是以ws://开头的地址;
  2. 请求头Upgrade: websocketConnection: Upgrade表示这个连接将要被转换为WebSocket连接;
  3. Sec-WebSocket-Key是用于标识这个连接,并非用于加密数据;
  4. Sec-WebSocket-Version指定了WebSocket的协议版本。

浏览器的response如下

1
2
3
4
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: server-random-string

状态码101的意思是

HTTP状态码

特点

建立在 TCP 协议之上,服务器端的实现比较容易

与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。

数据格式比较轻量,性能开销小,通信高效。

可以发送文本,也可以发送二进制数据。

没有同源限制,客户端可以与任意服务器通信

协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。

API

WebSocket MDN

简单例子

可以使用WebSocketd简单搭建一个服务器

WebSocketd可以使用brew下载