初次接触websocket是做公司的年会弹幕系统,当时就是短时间突击怎么使用,并没有深入理解原理。现在公司年会结束,抽时间整理一下,写这两篇博客出来。
1 网络协议的基本知识
首先我们来回顾一下OSI网络分层模型:
分层 | 功能 | CP/IP协议族 |
应用层 | 文件传输,电子邮件,文件服务,虚拟终端 | TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet |
表示层 | 数据格式化,代码转换,数据加密 | 没有协议 |
会话层 | 解除或建立与别的接点的联系 | 没有协议 |
传输层(运输层) | 提供端对端的接口 | TCP,UDP |
网络层 | 为数据包选择路由 | IP,ICMP,RIP,OSPF,BGP,IGMP |
数据链路层 | 传输有地址的帧以及错误检测功能 | SLIP,CSLIP,PPP,ARP,RARP,MTU |
物理层 | 以二进制数据形式在物理媒体上传输数据 | ISO2110,IEEE802。IEEE802.2 |
我们熟知的HTTP协议分为1.0和1.1。
HTTP1.0时期是不支持长连接的,也就是说,浏览器的每次请求都需要与服务器建立一个TCP连接,服务器完成请求处理后立即断开TCP连接,服务器不跟踪每个客户也不记录过去的请求。这样的问题在哪里?浏览器打开一个网页需要建立一次连接,打开这个网页中的每个图片又要建立一次连接。HTTP1.1则支持持久连接,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟。一个包含有许多图像的网页文件的多个请求和应答可以在一个连接中传输,但每个单独的网页文件的请求和应答仍然需要使用各自的连接。HTTP 1.1还允许客户端不用等待上一次请求结果返回,就可以发出下一次请求,但服务器端必须按照接收到客户端请求的先后顺序依次回送响应结果,以保证客户端能够区分出每次请求的响应内容,这样也显著地减少了整个下载过程所需要的时间。
HTTP 1.1还通过增加更多的请求头和响应头来改进和扩充HTTP 1.0的功能。在HTTP 1.1中增加Host请求头字段后,WEB浏览器可以使用主机头名来明确表示要访问服务器上的哪个WEB站点,这才实现了在一台WEB服务器上可以在同一个IP地址和端口号上使用不同的主机名来创建多个虚拟WEB站点。
无论是HTTP1.0还是1.1,都存在这样的缺陷:
1. 多次连接带来的性能损耗(即便是HTTP1.1,每个单独的网页文件的请求和应答仍然需要使用各自的连接)。
2. HTTP协议的会话都是客户端向服务器发起的。服务器不能主动发送消息给客户端。某些需要服务器向客户端推送通知的场景,客户端需要不断轮询服务器。
3. HTTP是非状态性的,每次都要重新传输鉴别信息,否则一旦断开一次,服务器就不知道客户端是谁了。
4. HTTP请求头信息多,传送很重。
2 轮询和长轮询
前面我们已经介绍过,HTTP协议中,服务器不能主动发送消息给客户端。在没有WebSocket的时候,客户端想要从服务器获取消息,主要有两种方式:轮询和长轮询。接下来就介绍一下这两种方式的问题。
所谓轮询,客户端每隔几秒发一个请求到服务器,问服务器有没有新的消息。没有则返回无,有就返回消息。再过几秒,客户端又会发送一个请求过来,整个过程持续下去。
所谓长轮询,客户端发送一个请求到服务器,问有没有新的消息。服务器会一直阻塞到有新消息才返回。
这两种方式中,服务器都是被动的。
3 什么是WebSocket
WebSocket并非一个工具,而是HTML5里面的协议。它从某种角度上弥补了上一部分中我们介绍过的HTTP协议的缺陷。
它诞生的最大价值,在于解决客户端和服务器之间的实时通信。WebSocket提供使用一个TCP连接进行双向通讯的机制,包括网络协议和API,以取代网页和服务器采用HTTP轮询进行双向通讯的机制。
由于使用WebSocket使用HTTP的端口,因此TCP连接建立后的握手消息是基于HTTP的,由服务器判断这是一个HTTP协议,还是WebSocket协议。WebSocket连接除了建立和关闭时的握手,数据传输和HTTP没有任何关系。
下面看看一次客户端与服务器之间的握手。客户端向服务器发送如下请求:
GET /chat HTTP/1.1 Host: server.example.com Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw== Sec-WebSocket-Protocol: chat, superchat Sec-WebSocket-Version: 13 Origin: http://example.com
可以看到,上面的握手请求中,
Upgrade: websocket Connection: Upgrade
表明这是WebSocket协议,而非HTTP协议。
然后服务器依据客户端的请求头信息,生成16位安全密钥(Sec-WebSocket-Accept)返回给客户端,就表示WebSocket连接成功。
HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk= Sec-WebSocket-Protocol: chat
一次握手成功之后,客户端和服务器之间就可以建立持久连接的双向传输数据通道,而且服务器不需要被动地等客户端的请求,服务器这边有新消息就可以通知客户端,化被动为主动。
此外,使用WebSocket时,不会像HTTP一样无状态,服务器会一直知道客户端的身份。服务器与客户端之间交换的标头信息也很小。
下一节中,我们将会介绍WebSocket的简单使用案例。