WebSocket剖析

WebSocket协议是HTML5定义的一种在单个TCP连接上进行全双工通信的协议,提供了比HTTP更高效、实时的通信方式。在WebSocket中,服务器可以主动向客户端推送数据,减少了轮询带来的资源浪费。握手过程涉及HTTP的101状态码,客户端通过Sec-WebSocket-Key等字段与服务器验证连接。本文详细介绍了WebSocket的工作原理,包括握手、通信示例和在tornado框架中的使用方法。
摘要由CSDN通过智能技术生成

WebSocket剖析

http协议

在了解WebSocket之前,有必要简单复习一下http协议。

请求和响应

Http协议用于客户端与服务端的通信,客户端发出请求(request),服务端返回响应(response)。下面我们以访问https://www.sogou.com/搜狗首页为例,来看看请求报文和响应报文:
下面是从客户端访问服务器的请求报文的截取内容:

GET / HTTP/1.1
Host: www.sogou.com
Connection: keep-alive
Cache-Control: max-age=0

第一行的GET表示请求方法;随后的 / 表示请求访问的资源对象(request-URI),这里是根页面;最后的HTTP/1.1是协议和版本号。
第二行开始是首部字段:Host字段表示服务器域名。(这里只截取了部分首部字段,实际的字段更多)
http请求报文由请求方法、URI、HTTP版本、HTTP首部字段构成。

下面是服务器返回的响应报文的截取内容:

HTTP/1.1 200 OK
Server: nginx
Date: Tue, 19 Sep 2017 08:37:38 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive

<html>
......

第一行的HTTP/1.1表示服务器对应的HTTP版本; 200 OK表示请求处理结果的状态码和原因短语。
第二行开始是首部字段,包括服务器安装的软件版本,响应日期等。
响应报文包括响应头和响应体。
响应头由HTTP版本、状态码、原因短语、首部字段组成。
最下面的<html>开始是响应体,也就是用户在浏览器上看到的具体网页,由两组\r\n换行符与上面的响应头分隔。

http是被动的协议

使用http协议,通信只能由客户端发起,服务端返回响应永远是被动的,不能由服务端主动发起。

http是非持久的协议

使用http协议通信时,需要不断地建立,关闭http连接。每当有新请求到达时,就会有对应的新的响应产生。一次请求,一次响应,结束,这就是http的生命周期。http1.1中多了一个keep-alive,在一次http连接中,可以发送多个请求,接收多个响应。但是一个请求只能有一个响应。

轮询和长轮询

如果希望实现持久连接的效果,比如在聊天室应用中,就要借助轮询(poll)或者长轮询(long poll)。简单来说,轮询就是客户端每隔几秒,就向服务端发送一次请求,询问是否有新消息。而长轮询则是阻塞模式,客户端发起请求后,一段时间内(web微信是25秒的样子,可以打开浏览器的开发者工具,查看Network,有一个pending状态,定期会刷新一次),服务端只要没有新消息,就不返回响应。一旦新消息到达或者超时,就返回响应给客户端,一次连接结束,客户端重新发起请求,周而复始。web QQ 和 web 微信,都是用长轮询做的。

轮询和长轮询效率低,消耗资源:

  • 轮询要求不停地连接,即浏览器隔几秒就要向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽资源。同理,服务器隔几秒就要返回响应,消息可能存在延时,不仅浪费带宽,还要求服务器有很快的处理速度。
  • 长轮询要求http连接始终打开,也会对服务器造成很大压力,要求服务器处理大并发的能力。

http是无状态协议

http协议本身并不保留之前的一切请求或响应报文的信息。这是为了更快地处理大量事物,确保协议的可伸缩性,也能减轻服务器的压力。而且由于不需要保存状态,http协议本身比较简单,能被应用在各种场景里。如果需要管理状态,需要借助Cookie和Session,在每次连接中,告诉服务端你是谁。

WebSocket

是什么

WebSocket协议是在HTML5中定义的,目前主流浏览器都支持这一标准。它能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。

WebSocket是一种在单个TCP连接上进行全双工通讯的协议。使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

主要特点

  • 较少的控制开销。在连接创建后,服务器和客户端之间交换数据时,用于协议控制的数据包头部相对较小。在不包含扩展的情况下,对于服务器到客户端的内容,此头部大小只有2至10字节(和数据包长度有关);对于客户端到服务器的内容,此头部还需要加上额外的4字节的掩码。相对于HTTP请求每次都要携带完整的头部,此项开销显著减少了。

  • 更强的实时性。由于协议是全双工的,所以服务器可以随时主动给客户端下发数据。相对于HTTP请求需要等待客户端发起请求服务端才能响应,延迟明显更少;即使是和Comet等类似的长轮询比较,其也能在短时间内更多次地传递数据。

  • 保持连接状态。与HTTP不同的是,Websocket需要先创建连接,这就使得其成为一种有状态的协议,之后通信时可以省略部分状态信息。而HTTP请求可能需要在每个请求都携带状态信息(如身份认证等)。

  • 更好的二进制支持。Websocket定义了二进制帧,相对HTTP,可以更轻松地处理二进制内容。

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

  • Websocket使用ws或wss的统一资源标志符,比如:ws://example.com/path。类似于HTTPS,其中wss表示在TLS之上的Websocket。Websocket使用和 HTTP 相同的 TCP 端口,可以绕过大多数防火墙的限制。默认情况下,Websocket协议使用80端口;运行在TLS之上时,默认使用443端口。

    bg2017051503

握手过程

为了创建Websocket连接,需要通过浏览器发出请求,之后服务器进行回应,这个过程通常称为“握手”(handshaking)。Websocket 通过 HTTP/1.1 协议的101状态码进行握手。过程如下:

客户端请求

GET / HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Host: example.com
Origin: http://example.com
Sec-WebSocket-Key: sN9cRrP/n9NdMgdcy2VJFQ==
Sec-WebSocket-Version: 13

服务端回应

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: fFBooB7FAkLlXgRSz0BT3v4hq5s=
Sec-WebSocket-Location: ws://example.com/

说明

  • Connection必须设置Upgrade,表示客户端希望连接升级
  • Upgrade字段必须设置Websocket,表示希望升级到Websocket协议
  • Sec-WebSocket-Key是随机的字符串,作验证用的,为了避免和HTTP请求混淆:
    • 服务端提取Sec-WebSocket-Key
    • 将一个特殊字符串(magic_string)和Sec-WebSocket-Key先进行SHA-1摘要计算,之后进行BASE-64编码
    • 编码结果作为响应头Sec-WebSocket-Accept字段的值,返回给客户端
    • 客户端将这个值和本地计算的值对比,如果一致,则进行Websocket通信
  • Sec-WebSocket-Version 表示支持的Websocket版本。RFC6455要求使用的版本是13,之前草案的版本均应当弃用
  • 其他一些定义在HTTP协议中的字段,比如cookie,也可以在Websocket中使用。

客户端和服务端通过Websocket通信示例

客户端和服务端传输数据时,需要对数据进行【封包】和【解包】。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值