WebSocket是HTML5新增的协议,它的目的是在浏览器和服务器之间建立一个不受限的双向通信的通道,比如说,服务器可以在任意时刻发送消息给浏览器。
为什么传统的HTTP协议不能做到WebSocket实现的功能?这是因为HTTP协议是一个请求-响应协议,请求必须先由浏览器发给服务器,服务器才能响应这个请求,再把数据发送给浏览器。换句话说,浏览器不主动请求,服务器是没法主动发数据给浏览器的。
这样一来,要在浏览器中搞一个实时聊天,在线炒股(不鼓励),或者在线多人游戏的话就没法实现了,只能借助Flash这些插件。
也有人说,HTTP协议其实也能实现啊,比如用轮询或者Comet。轮询是指浏览器通过JavaScript启动一个定时器,然后以固定的间隔给服务器发请求,询问服务器有没有新消息。这个机制的缺点一是实时性不够,二是频繁的请求会给服务器带来极大的压力。
Comet本质上也是轮询,但是在没有消息的情况下,服务器先拖一段时间,等到有消息了再回复。这个机制暂时地解决了实时性问题,但是它带来了新的问题:以多线程模式运行的服务器会让大部分线程大部分时间都处于挂起状态,极大地浪费服务器资源。另外,一个HTTP连接在长时间没有数据传输的情况下,链路上的任何一个网关都可能关闭这个连接,而网关是我们不可控的,这就要求Comet连接必须定期发一些ping数据表示连接“正常工作”。
以上两种机制都治标不治本,所以,HTML5推出了WebSocket标准,让浏览器和服务器之间可以建立无限制的全双工通信,任何一方都可以主动发消息给对方。
WebSocket协议
WebSocket并不是全新的协议,而是利用了HTTP协议来建立连接。我们来看看WebSocket连接是如何创建的。
首先,WebSocket连接必须由浏览器发起,因为请求协议是一个标准的HTTP请求,格式如下:
GET ws://localhost:3000/ws/chat HTTP/1.1Host: localhost Upgrade: websocket Connection: Upgrade Origin: http://localhost:3000Sec-WebSocket-Key: client-random-string Sec-WebSocket-Version: 13
该请求和普通的HTTP请求有几点不同:
GET请求的地址不是类似
/path/
,而是以ws://
开头的地址;请求头
Upgrade: websocket
和Connection: Upgrade
表示这个连接将要被转换为WebSocket连接;Sec-WebSocket-Key
是用于标识这个连接,并非用于加密数据;Sec-WebSocket-Version
指定了WebSocket的协议版本。
随后,服务器如果接受该请求,就会返回如下响应:
HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: server-random-string
该响应代码101
表示本次连接的HTTP协议即将被更改,更改后的协议就是Upgrade: websocket
指定的WebSocket协议。
版本号和子协议规定了双方能理解的数据格式,以及是否支持压缩等等。如果仅使用WebSocket的API,就不需要关心这些。
现在,一个WebSocket连接就建立成功,浏览器和服务器就可以随时主动发送消息给对方。消息有两种,一种是文本,一种是二进制数据。通常,我们可以发送JSON格式的文本,这样,在浏览器处理起来就十分容易。
为什么WebSocket连接可以实现全双工通信而HTTP连接不行呢?实际上HTTP协议是建立在TCP协议之上的,TCP协议本身就实现了全双工通信,但是HTTP协议的请求-应答机制限制了全双工通信。WebSocket连接建立以后,其实只是简单规定了一下:接下来,咱们通信就不使用HTTP协议了,直接互相发数据吧。
安全的WebSocket连接机制和HTTPS类似。首先,浏览器用wss://xxx
创建WebSocket连接时,会先通过HTTPS创建安全的连接,然后,该HTTPS连接升级为WebSocket连接,底层通信走的仍然是安全的SSL/TLS协议。
一、websocket与http
WebSocket是HTML5出的东西(协议),也就是说HTTP协议没有变化,或者说没关系,但HTTP是不支持持久连接的(长连接,循环连接的不算)
首先HTTP有 1.1
和 1.0
之说,也就是所谓的 keep-alive
,把多个HTTP请求合并为一个,但是 Websocket
其实是一个新协议,跟HTTP协议基本没有关系,只是为了兼容现有浏览器的握手规范而已,也就是说它是HTTP协议上的一种补充可以通过这样一张图理解
有交集,但是并不是全部。
另外Html5是指的一系列新的API,或者说新规范,新技术。Http协议本身只有1.0和1.1,而且跟Html本身没有直接关系。。通俗来说,你可以用HTTP协议传输非Html数据,就是这样=。=
再简单来说,层级不一样。
二、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
握手(借用Wikipedia的。。)
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的童鞋可能发现了,这段类似HTTP协议的握手请求中,多了几个东西。我会顺便讲解下作用。
Upgrade: websocket Connection: Upgrade
这个就是Websocket的核心了,告诉 Apache
、 Nginx
等服务器:注意啦,我发起的是Websocket协议,快点帮我找到对应的助理处理~不是那个老土的HTTP。
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw== Sec-WebSocket-Protocol: chat, superchat Sec-WebSocket-Version: 13
首先, Sec-WebSocket-Key
是一个 Base64 encode
的值,这个是浏览器随机生成的,告诉服务器:泥煤,不要忽悠窝,我要验证尼是不是真的是Websocket助理。
然后, Sec_WebSocket-Protocol
是一个用户定义的字符串,用来区分同URL下,不同的服务所需要的协议。简单理解:今晚我要服务A,别搞错啦~
最后, Sec-WebSocket-Version
是告诉服务器所使用的 Websocket Draft
(协议版本),在最初的时候,Websocket协议还在 Draft
阶段,各种奇奇怪怪的协议都有,而且还有很多期奇奇怪怪不同的东西,什么Firefox和Chrome用的不是一个版本之类的,当初Websocket协议太多可是一个大难题。。不过现在还好,已经定下来啦~大家都使用的一个东西~ 脱水: 服务员,我要的是13岁的噢→_→
然后服务器会返回下列东西,表示已经接受到请求, 成功建立Websocket啦!
HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk= Sec-WebSocket-Protocol: chat
这里开始就是HTTP最后负责的区域了,告诉客户,我已经成功切换协议啦~
Upgrade: websocket Connection: Upgrade
依然是固定的,告诉客户端即将升级的是 Websocket
协议,而不是mozillasocket,lurnarsocket或者shitsocket。
然后, Sec-WebSocket-Accept
这个则是经过服务器确认,并且加密过后的 Sec-WebSocket-Key
。 服务器:好啦好啦,知道啦,给你看我的ID CARD来证明行了吧。。
后面的, Sec-WebSocket-Protocol
则是表示最终使用的协议。
至此,HTTP已经完成它所有工作了,接下来就是完全按照Websocket协议进行了。具体的协议就不在这阐述了。
二、Websocket实例
<!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <title>菜鸟教程(runoob.com)</title> <script type="text/javascript"> function WebSocketTest() { if ("WebSocket" in window) { alert("您的浏览器支持 WebSocket!"); // 打开一个 web socket var ws = new WebSocket("ws://localhost:9998/echo"); ws.onopen = function() { // Web Socket 已连接上,使用 send() 方法发送数据 ws.send("发送数据"); alert("数据发送中..."); }; ws.onmessage = function (evt) { var received_msg = evt.data; alert("数据已接收..."); }; ws.onclose = function() { // 关闭 websocket alert("连接已关闭..."); }; } else { // 浏览器不支持 WebSocket alert("您的浏览器不支持 WebSocket!"); } } </script> </head> <body> <div id="sse"> <a href="javascript:WebSocketTest()">运行 WebSocket</a> </div> </body> </html>
- 本文固定链接: http://ttfde.top/index.php/post/412.html
- 转载请注明: admin 于 TTF的家园 发表
《本文》有 0 条评论