定义
WebSocket
一种在单个 TCP
连接上进行全双工通讯的协议,WebSocket
是独立的、创建在 TCP
上的协议,和 HTTP
的唯一关联是使用 HTTP
协议的101状态码进行协议切换,WebSocket
使得客户端和服务器之间的数据交换变得更加简单,允许服务端直接向客户端推送数据而不需要客户端进行请求,在 WebSocket API
API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并允许数据进行双向传送。
背景
现在,很多网站为了实现推送技术,所用的技术都是轮询。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP request
,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP request
的header是非常长的,里面包含的数据可能只是一个很小的值,这样会占用很多的带宽和服务器资源。
而比较新的技术去做轮询的效果是Comet,使用了AJAX。但这种技术虽然可达到双向通信,但依然需要发出请求,而且在Comet中,普遍采用了长链接,这也会大量消耗服务器带宽和资源。
面对这种状况,HTML5
定义了WebSocket
协议,能更好的节省服务器资源和带宽并达到实时通讯。
支持情况
WebSocket
跟其他 API 比较不一样的是,它不仅仅依赖于浏览器支持,同时要求服务器和代理(假若需要经过代理的话)支持。WebSocket
本质上跟 HTTP
完全不一样,只不过为了兼容性,WebSocket
的握手是以 HTTP
的形式发起的,如果服务器或者代理不支持 WebSocket
,它们会把这当做一个不认识的 HTTP
请求从而优雅地拒绝掉。
WebSocket
是什么样的协议
WebSocket
是基于HTTP协议的,或者说借用了HTTP的协议来完成一部分握手。
在握手阶段是一样的
首先我们来看个典型的WebSocket
握手
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
比普通的 http请求头多了几个东西
Upgrade: websocket
Connection: Upgrade
这个就是WebSocket
的核心了,告诉Apache、Nginx
等服务器:发起的是WebSocket
协议
然后服务器会返回下列东西,表示已经接受到请求, 成功建立WebSocket
啦!
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat
WebSocket
的作用
先讲一下ajax
轮询和长轮询的原理
轮询是一种“拉”取信息的工作模式。设置一个定时器,定时询问服务器是否有信息,每次建立连接传输数据之后,链接会关闭
在轮询的过程中,如果因为网络原因,导致上一个 xhr 对象还没传输完毕,定时器已经开始了下一个询问,下一个会直接覆盖上一个,即便前一个返回了,也不会认了
长轮询和ajax轮询都是采用轮询的方式,不过采取的是阻塞模型(一直打电话,没收到就不挂电话),也就是说,客户端发起连接后,如果没消息,就一直不返回Response给客户端。直到有消息才返回。只要服务器断开连接,客户端马上连接,不让他有一刻的休息时间
从上面可以看出其实这两种方式,都是在不断发起HTTP
连接,然后等待服务端处理,可以体现HTTP
协议的另外一个特点,被动性。
何为被动性呢,其实就是,服务端不能主动联系客户端,只能有客户端发起
不管怎么样,上面这两种都是非常消耗资源的。
ajax轮询 需要服务器有很快的处理速度和资源。(速度)
long poll 需要有很高的并发,也就是说同时接待客户的能力。(场地大小)
WebSocket
解决了HTTP
的这几个难题。
首先,被动性,当服务器完成协议升级后(HTTP
->WebSocket
),服务端就可以主动推送信息给客户端啦。
就变成了这样,只需要经过一次HTTP
请求,就可以做到源源不断的信息传送了
其实我们所用的程序是要经过两层代理的,即HTTP
协议在Nginx
等服务器的解析下,然后再传送给相应的Handler(PHP等)来处理。
简单地说,我们有一个非常快速的接线员(Nginx
),他负责把问题转交给相应的客服(Handler)。
本身接线员基本上速度是足够的,但是每次都卡在客服(Handler)了,老有客服处理速度太慢。,导致客服不够。WebSocket
就解决了这样一个难题,建立后,可以直接跟接线员建立持久连接,有信息的时候客服想办法通知接线员,然后接线员在统一转交给客户。
这样就可以解决客服处理速度过慢的问题了。
同时,在传统的方式上,要不断的建立,关闭HTTP
协议,由于HTTP
是非状态性的,每次都要重新传输identity info(鉴别信息),来告诉服务端你是谁。
虽然接线员很快速,但是每次都要听这么一堆,效率也会有所下降的,同时还得不断把这些信息转交给客服,不但浪费客服的处理时间,而且还会在网路传输中消耗过多的流量/时间。
但是WebSocket
只需要一次HTTP
握手,所以说整个通讯过程是建立在一次连接/状态中,也就避免了HTTP
的非状态性,服务端会一直知道你的信息,直到你关闭请求,这样就解决了接线员要反复解析HTTP
协议,还要查看identity info的信息。
同时由客户主动询问,转换为服务器(推送)有信息的时候就发送(当然客户端还是等主动发送信息过来的。。),没有信息的时候就交给接线员(Nginx),不需要占用本身速度就慢的客服(Handler)了
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。