1 序言
本文紧张阐发了 WebSocket 的事理,以及附上一个完全的谈天室实战 Demo (包含前端和后端,代码下载链接在文末)。
2 WebSocket 与 HTTP

WebSocket 协议在2008年出身,2011年景为国际标准。现在所有浏览器都已经支持了。WebSocket 的最大特点便是,做事器可以主动向客户端推送信息,客户端也可以主动向做事器发送信息,是真正的双向平等对话。
HTTP 有 1.1 和 1.0 之说,也便是所谓的 keep-alive ,把多个 HTTP 要求合并为一个,但是 Websocket 实在是一个新协议,跟 HTTP 协议基本没有关系,只是为了兼容现有浏览器,以是在握手阶段利用了 HTTP 。
下面一张图解释了 HTTP 与 WebSocket 的紧张差异:
WebSocket 的其他特点:
建立在 TCP 协议之上,做事器真个实现比较随意马虎。
与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采取 HTTP 协议,因此握手时不随意马虎屏蔽,能通过各种 HTTP 代理做事器。
数据格式比较轻量,性能开销小,通信高效。
可以发送文本,也可以发送二进制数据。
没有同源限定,客户端可以与任意做事器通信。
协议标识符是ws(如果加密,则为wss),做事器网址便是 URL。
3 WebSocket 是什么样的协议,详细有什么优点
首先,WebSocket 是一个持久化的协议,相对付 HTTP 这种非持久的协议来说。大略的举个例子吧,用目前运用比较广泛的 PHP 生命周期来阐明。
HTTP 的生命周期通过 Request 来界定,也便是一个 Request 一个 Response ,那么在 HTTP1.0 中,这次 HTTP 要求就结束了。
在 HTTP1.1 中进行了改进,使得有一个 keep-alive,也便是说,在一个 HTTP 连接中,可以发送多个 Request,吸收多个 Response。但是请记住 Request = Response, 在 HTTP 中永久是这样,也便是说一个 Request 只能有一个 Response。而且这个 Response 也是被动的,不能主动发起。
你 BB 了这么多,跟 WebSocket 有什么关系呢?好吧,我正准备说 WebSocket 呢。
首先 WebSocket 是基于 HTTP 协议的,或者说借用了 HTTP 协议来完成一部分握手。
首先我们来看个范例的 WebSocket 握手
GET /chat HTTP/1.1Host: server.example.comUpgrade: websocketConnection: UpgradeSec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==Sec-WebSocket-Protocol: chat, superchatSec-WebSocket-Version: 13Origin: http://example.com
熟习 HTTP 的童鞋可能创造了,这段类似 HTTP 协议的握手要求中,多了这么几个东西。
Upgrade: websocketConnection: Upgrade
这个便是 WebSocket 的核心了,见告 Apache 、 Nginx 等做事器:把稳啦,我发起的要求要用 WebSocket 协议,快点帮我找到对应的助理处理~而不是那个老土的 HTTP。
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==Sec-WebSocket-Protocol: chat, superchatSec-WebSocket-Version: 13
首先, Sec-WebSocket-Key 是一个 Base64 encode 的值,这个是浏览器随机天生的,见告做事器:泥煤,不要忽悠我,我要验证你是不是真的是 WebSocket 助理。
然后, Sec_WebSocket-Protocol 是一个用户定义的字符串,用来区分同 URL 下,不同的做事所须要的协议。大略理解:今晚我要做事A,别搞错啦~
末了, Sec-WebSocket-Version 是见告做事器所利用的 WebSocket Draft (协议版本),在最初的时候,WebSocket 协议还在 Draft 阶段,各种奇奇怪怪的协议都有,而且还有很多期奇奇怪怪不同的东西,什么 Firefox 和 Chrome 用的不是一个版本之类的,当初 WebSocket 协议太多可是一个大难题。。不过现在还好,已经定下来啦~大家都利用同一个版本:做事员,我要的是.....→_→
然后做事器会返回下列东西,表示已经接管到要求, 成功建立 WebSocket 啦!
HTTP/1.1 101 Switching ProtocolsUpgrade: websocketConnection: UpgradeSec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=Sec-WebSocket-Protocol: chat
这里开始便是 HTTP 末了卖力的区域了,见告客户,我已经成功切换协议啦~
Upgrade: websocketConnection: Upgrade
依然是固定的,见告客户端即将升级的是 WebSocket 协议,而不是 mozillasocket,lurnarsocket 或者 shitsocket。
然后, Sec-WebSocket-Accept 这个则是经由做事器确认,并且加密过后的 Sec-WebSocket-Key 。做事器:好啦好啦,知道啦,给你看我的 ID CARD 来证明行了吧。
后面的, Sec-WebSocket-Protocol 则是表示终极利用的协议。
至此,HTTP 已经完成它所有事情了,接下来便是完备按照 WebSocket 协议进行了。
4 WebSocket的浸染
在讲 WebSocket之前,我就顺带着讲下 ajax轮询 和 long poll 的事理。
4.1 ajax轮询
ajax轮询的事理非常大略,让浏览器隔个几秒就发送一次要求,讯问做事器是否有新信息。
场景再现:
客户端:啦啦啦,有没有新信息(Request)做事端:没有(Response)客户端:啦啦啦,有没有新信息(Request)做事端:没有。。(Response)客户端:啦啦啦,有没有新信息(Request)做事端:你好烦啊,没有啊。。(Response)客户端:啦啦啦,有没有新(Request)做事端:好啦好啦,有啦给你。(Response)客户端:啦啦啦,有没有新(Request)做事端:。。。。。没。。。。没。。。没有(Response) —- loop
4.2 long poll
long poll 实在事理跟 ajax轮询 差不多,都是采取轮询的办法,不过采纳的是壅塞模型(一贯打电话,没收到就不挂电话),也便是说,客户端发起要求后,如果没,就一贯不返回 Response 给客户端。直到有才返回,返回完之后,客户端再次建立连接,周而复始。
场景再现:
客户端:啦啦啦,有没有新信息,没有的话就等有了才返回给我吧(Request)做事端:额。。等待到有的时候。。来 给你(Response)客户端:啦啦啦,有没有新信息,没有的话就等有了才返回给我吧(Request) -loop
从上面可以看出实在这两种办法,都是在不断地建立HTTP连接,然后等待做事端处理,可以表示HTTP协议的其余一个特点,被动性。
作甚被动性呢,实在便是,做事端不能主动联系客户端,只能有客户端发起。
从上面很随意马虎看出来,不管怎么样,上面这两种都是非常花费资源的。
ajax轮询 须要做事器有很快的处理速率和资源。long poll 须要有很高的并发,也便是说同时接待客户的能力。
以是 ajax轮询 和 long poll 都有可能发生这种情形。
客户端:啦啦啦啦,有新信息么?做事端:正忙,请稍后再试(503 Server Unavailable)客户端:。。。。好吧,啦啦啦,有新信息么?做事端:正忙,请稍后再试(503 Server Unavailable)
4.3 WebSocket
通过上面这两个例子,我们可以看出,这两种办法都不是最好的办法,须要很多资源。
一种须要更快的速率,一种须要更多的'电话'。这两种都会导致’电话’的需求越来越高。
哦对了,忘却说了 HTTP 还是一个无状态协议。普通的说便是,做事器由于每天要接待太多客户了,是个健忘鬼,你一挂电话,他就把你的东西全忘光了,把你的东西全丧失落了。你第二次还得再见告做事器一遍。
以是在这种情形下涌现了 WebSocket 。他办理了 HTTP 的这几个难题。首先,被动性,当做事器完成协议升级后(HTTP->Websocket),做事端就可以主动推送信息给客户端啦。以是上面的情景可以做如下修正。
客户端:啦啦啦,我要建立Websocket协议,须要的做事:chat,Websocket协议版本:17(HTTP Request)做事端:ok,确认,已升级为Websocket协议(HTTP Protocols Switched)客户端:麻烦你有信息的时候推送给我噢。。做事端:ok,有的时候会见告你的。做事端:balabalabalabala做事端:balabalabalabala做事端:哈哈哈哈哈啊哈哈哈哈做事端:笑去世我了哈哈哈哈哈哈哈
这样,只须要经由一次 HTTP 要求,就可以做到源源不断的信息传送了。
5 实战代码
参考文档:
php socket 文档:https://php.net/manual/zh/ref.sockets.phpjs 的 WebSocket 文档:https://developer.mozilla.org/en-US/docs/Web/API/WebSocket
前端代码:
https://github.com/nnngu/WebSocketDemo-js
后端代码:
https://github.com/nnngu/WebSocketDemo-php
运行步骤:
在终端打开 WebSocketDemo-php 目录,实行 php -q server.php 用浏览器访问 WebSocketDemo-js 目录里面的 index.html
运行截图:
本日就分享这么多,希望对大家有所帮助。
末了,我自己是一名从事了多年开拓的Python老程序员,辞职目前在做自己的Python私人定制课程,今年年初我花了一个月整理了一份最适宜2019年学习的Python学习干货,可以送给每一位喜好Python的小伙伴,想要获取的可以关注我的头条号并在后台私信我:01,即可免费获取。