html5 新增 websocket(2) 原理

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/CJXBShowZhouyujuan/article/details/77746396
我们在上篇文章中说道websocket是一个 客户端服务器端之间进行的 非HTTP的通信机制,是双向的、实时的、永久的。

http的工作原理

(1)http协议是在应用层的协议,是基于TCP的,http连接的建立需要3次握手才能发送消息。
这篇文章详细的介绍了握手的过程。
这篇文章列举了http的Header的信息。

WebSocket是HTML5出的协议。是一个新的协议,和HTTP是没有太多的关系的。是为了兼容现有浏览器的握手规范而已。

(2)http 链接分为短链接,长链接。

短链接:每次请求都要三次握手才能发送自己的信息。HTTP的生命周期通过Request来界定,也就是一个Request一个Response。那么 HTTP1.0 ,这次HTTP请求就结束了。下次再次链接就需要再次请求。

长链接:是在一定的期限内保持链接。保持TCP连接不断开。客户端与服务器通信,必须要有客户端发起然后服务器返回结果。客户端是主动的,服务器是被动的。
在HTTP1.1中进行了改进,使得有一个keep-alive,也就是说,在一个HTTP连接中,可以发送多个Request,接收多个Response。

但是请记住 Request = Response ,在HTTP中永远是这样,也就是说一个request只能有一个response。而且这个response也是 被动 的,不能主动发起。

(3)websocket的握手。

websocket也是基于HTTP协议的,不过是他只需经历一次握手就可以,建立连接,并且这个链接是双向的是永久了,除非显示的断开。
上一篇文章中其实也用图片展示了这次握手的表现。


看过了上面关于HTTP请求头的链接文章后,你会发先,这个websocket的请求多了一些东西。
connection:Upgrade
Upgrade:websocket.
上一篇中提到了,这个就是websocket的核心了。就是告诉服务器我发起的是一个websocket协议。
Sec_WebSocket_Key:是一个Base64encode的值,是由浏览器随机生成的。用来验证链接到的是不是WebSocket.
Sec-WebSocket-Version 是告诉服务器所使用的Websocket Draft(协议版本)



这里服务器给了返回值了。
Upgrade: websocketConnection: Upgrade
这就是告诉客户我这里已经切换成功了。升级为WebSocket
Sec-WebSocket-Accept这个则是经过服务器确认,并且加密过后的 Sec-WebSocket-Key。
总结:
经过这个的握手,客户端和服务器端就握手成功了。建立起来了websocket的链接了。

(4)在没有websocket时时如何处理的

我们看到了websocket是双向的,实时的,永久的。便捷的地方就是服务器可以主动的给客户端发送消息。

场景:推送,服务器有一条新的消息,需要通知到客户端,可是客户端还没有来请求,那么这条新消息就不能发送出去。

这种场景在websocket中是很容易实现的,因为连接是一直存在的,服务器可以主动的发送消息。

在没有websocket的时候,我们使用的方法就是,long poll 或者 ajax轮询。

首先 ajax轮询的实现原理
参考了知乎上的一篇文章

场景再现:
客户端:啦啦啦,有没有新信息(Request)
服务端:没有(Response)
客户端:啦啦啦,有没有新信息(Request)
服务端:没有。。(Response)
客户端:啦啦啦,有没有新信息(Request)
服务端:你好烦啊,没有啊。。(Response)
客户端:啦啦啦,有没有新消息(Request)
服务端:好啦好啦,有啦给你。(Response)
客户端:啦啦啦,有没有新消息(Request)
服务端:。。。。。没。。。。没。。。没有(Response) ---- loop

很形象的描述了ajax轮询的场景。每隔几秒就会向服务器发起请求,询问服务器是否有新的消息。不过http的请求是无状态的,所以服务器是不会记住,所以他也不会烦的。

long poll

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

这个的原理和 ajax差不多,不过,这里是阻塞的,就是发起了询问的请求之后,如果没有就一直等在哪里。

这两种形式就是在表示 http请求的一个“被动性”的特点。就是服务器不会主动联系客户端的。

综上:可以看出来了,这种情况很浪费资源。

那么WebSocket是如何做的
所以上面的情景可以做如下修改。
客户端:啦啦啦,我要建立Websocket协议,需要的服务:chat,Websocket协议版本:17(HTTP Request)
服务端:ok,确认,已升级为Websocket协议(HTTP Protocols Switched)
客户端:麻烦你有信息的时候推送给我噢。。
服务端:ok,有的时候会告诉你的。
服务端:balabalabalabala
服务端:balabalabalabala
服务端:哈哈哈哈哈啊哈哈哈哈
服务端:笑死我了哈哈哈哈哈哈哈

只需要一次的请求,然后就是源源不断的信息传递了。

此外还有 multiplexing 功能,几个不同的 URI 可以复用同一个 WebSocket 连接。这些都是原来的 HTTP 不能做到的。

下面是在知乎上看到的,拿到这里和大家分享一下

链接:https://www.zhihu.com/question/20215561/answer/40250050

另外说一点技术细节,因为看到有人提问 WebSocket 可能进入某种半死不活的状态。这实际上也是原有网络世界的一些缺陷性设计。上面所说的 WebSocket 真.长连接虽然解决了服务器和客户端两边的问题,但坑爹的是网络应用除了服务器和客户端之外,另一个巨大的存在是中间的网络链路。一个 HTTP/WebSocket 连接往往要经过无数的路由,防火墙。你以为你的数据是在一个“连接”中发送的,实际上它要跨越千山万水,经过无数次转发,过滤,才能最终抵达终点。在这过程中,中间节点的处理方法很可能会让你意想不到。

比如说,这些坑爹的中间节点可能会认为一份连接在一段时间内没有数据发送就等于失效,它们会自作主张的切断这些连接。在这种情况下,不论服务器还是客户端都不会收到任何提示,它们只会一厢情愿的以为彼此间的红线还在,徒劳地一边又一边地发送抵达不了彼岸的信息。而计算机网络协议栈的实现中又会有一层套一层的缓存,除非填满这些缓存,你的程序根本不会发现任何错误。这样,本来一个美好的 WebSocket 长连接,就可能在毫不知情的情况下进入了半死不活状态。

而解决方案,WebSocket 的设计者们也早已想过。就是让服务器和客户端能够发送 Ping/Pong Frame( RFC 6455 - The WebSocket Protocol)。这种 Frame 是一种特殊的数据包,它只包含一些元数据而不需要真正的 Data Payload,可以在不影响 Application 的情况下维持住中间网络的连接状态。

猜你喜欢

转载自blog.csdn.net/CJXBShowZhouyujuan/article/details/77746396