websocket 历史及使用详解

1、阅前热身

什么是keep-alive

一、keep-alive只是客户端的一种建议

咱们打开百度首页,进一步查看header。javascript

image_1b2idfp2k4ecu8pagh1mkutf39.png-415.7kB

如图,咱们看到请求header中有一行:php

Connection:keep-alive复制代码

keep-alive是通知服务器,在这个HTTP Request/Responset结束后,不要当即断开TCP链接(注意是TCP链接,和HTTP没有关系),后面的HTTP Request仍然能够经过这个TCP链接继续传送。java

可是!这只是个建议,服务器可能不支持,也可能忽略掉这个建议。也可能由于时间过久而直接断开TCP链接nginx

通俗点解释就是:keep-alive只是通知服务器,您先别挂,一下子可能还有活儿,至于它挂不挂仍是看它心情。web

因此,keep-alive只是客户端建议的一种复用TCP链接的方式,至于服务器支持不支持,就由不得客户端了。ajax

二、keep-alive只是http协议中的一部分

keep-alive是http协议中的一部分,也即客户端能够主动的发起request到服务器,服务器只能被动的response给客户端。segmentfault

我要想实现服务器主动的push消息给客户端,keep-alive是无能无力的。浏览器

2、服务器的消息如何发给客户端

long long ago~ 服务器端要想主动的push消息给客户端(好比网页聊天室消息的即时收发),这是不可能滴。
可是,我能够使用ajax轮询、long poll 技术造一个服务端给客户端主动push消息的假象。服务器

①:什么是ajax轮询?

ajax轮询的原理很是简单,让浏览器隔个几秒就发送一次请求,询问服务器是否有新信息。websocket

场景再现:

客户端:啦啦啦,有没有新信息(Request)
服务端:没有(Response)
客户端:啦啦啦,有没有新信息(Request)
服务端:没有。。(Response)
客户端:啦啦啦,有没有新信息(Request)
服务端:你好烦啊,没有啊。。(Response)
客户端:啦啦啦,有没有新消息(Request)
服务端:好啦好啦,有啦给你。(Response)
客户端:啦啦啦,有没有新消息(Request)
服务端:。。。。。没。。。。没。。。没有(Response) ---- loop复制代码

可是这样,有没有发现,大大增长了服务端的负载,而且速度还慢。

②:什么是long poll?

long poll和ajax差很少,原理都是采用轮询的方式。只不过long poll是采起的阻塞的方式去轮询。
也即客户端发起一个请求链接,这个链接会阻塞住,直到服务端有了消息,才会response给客户端。

注:阻塞、非阻塞的理解,请参考我以前的文章:nginx、swoole高并发原理初探

场景再现:

客户端:啦啦啦,有没有新信息,没有的话就等有了才返回给我吧(Request)
服务端:额。。 等待到有消息的时候。。来 给你(Response)
客户端:啦啦啦,有没有新信息,没有的话就等有了才返回给我吧(Request) -loop复制代码

long pull 虽然下降了服务器的负载,可是须要服务器有很高的并发能力才能够。
而目前处理高并发的模型基本都是异步非阻塞的模型(好比nginx)。

既想阻塞,又想高并发,几乎不可能。

③:总结

ajax轮询、long poll技术虽然都能实现服务端消息的实时通知,可是各有缺点,都不是根本的解决办法。
计算机界急需一种新的技术去处理这些需求~

3、websocket来啦

既然ajax轮询、long poll都不怎么样。咱们发明一种新的协议吧!

Websocket协议解决了服务器与客户端全双工通讯的问题。

注:什么是单工、半双工、全工通讯?
信息只能单向传送为单工;
信息能双向传送但不能同时双向传送称为半双工;
信息可以同时双向传送则称为全双工。

websocket协议解析

wensocket协议包含两部分:一部分是“握手”,一部分是“数据传输”。
为了便于演示,咱们采用swoole创建一个websocket服务器来演示。

一、握手

①客户端向服务端发起链接请求

image_1b2igg66d159v128qt59v2l48cm.png-59.3kB

如图,咱们在请求服务器的时候,发送了这样的request header。

下面咱们就一些比较重要的字段信息进行说明:

Connection:Upgrade #通知服务器协议升级
Upgrade:websocket  #协议升级为websocket协议
Host:0.0.0.0:9501  #升级协议的服务主机:端口地址
Sec-WebSocket-Key:K8o1cNIxO2pR6inTIDBSgg== #传输给服务器的key
Sec-WebSocket-Version:13 #websocket协议版本13复制代码

Sec-WebSocket-Key有什么用呢?
客户端将这个key发送给服务器,服务器将这个key进行处理,将处理后的key返回给客户端,客户端根据这个key是否正确来判断是否创建链接。

②:服务端返回握手应答

image_1b2ih7ard1oet1kangfig2uo01g.png-14.7kB

如图,咱们看到websocket协议状态码是101.

101表示协议切换成功。


咱们查看websocket的response header。如图:

image_1b2ih030qjdc1dllmshto0eph13.png-29.6kB

下面解释下reponse header字段的含义

Connection:Upgrade #协议升级成功
Sec-WebSocket-Accept:GnoYH/ip/ZMh+a5rX5P/YR6e68g= #服务端处理以后的key
Sec-WebSocket-Version:13#websocket 协议版本号
Upgrade:websocket#协议升级为websocket复制代码

至此,websocket握手成功!下面就尽情的传输数据吧!

二、数据传输

数据传输须要客户端,没什么好说的了。

  • Chrome/Firefox/高版本IE/Safari等浏览器内置了JS语言的WebSocket客户端
  • 能够使用一些扩展来实现websocket客户端。如php的swoole、workerman。

    注意:非WebSocket客户端不能与WebSocket服务器通讯

4、参考文章

Websocket协议之握手链接
WebSocket 是什么原理?为何能够实现持久链接?

更多精彩,请关注公众号“聊聊代码”,让咱们一块儿聊聊“左手代码右手诗”的事儿。