最近在接到用户需求的时候,希望做到多端协同登录的时候,能够让客户端展示的二维码展示已扫描、已登录等变化,给用户有好的操作体验。这是就存在着多端协实现客户端与服务端双向通信的问题。对于网页端就需要有接收服务器端消息的方式。这样就提出了一个问题,服务端与客户端双向通信有哪些方式?常用的方式有短轮询、Comet(长轮询、流技术)、http长连接、Websocket四大类五种方式。下面就分别聊一下着这五种方式。
一、短轮询(Ajax轮询)
http短轮询是服务器收到请求不管是否有数据都直接响应 http 请求; 浏览器受到 http 响应隔一段时间在发送同样的http 请求查询是否有数据。这种交互的图例如下:
短轮询的方式通过Ajax的定时请求,能够实现对服务器的应答,是最简单的方式实现,但是他是有局限性的,那就是实时性低,当等待时期(interval)比较长时,服务器的已处理好的数据就需要等待期过了才能返回给前端。同时,在数据没有加工好数据前,服务器所有的应答都是无意义的,系统开销会比较大。
二、长轮询 (long-polling)
http长轮询comet的一种,是服务器收到请求后如果有数据, 立刻响应请求; 如果没有数据就会等待一段时间,这段时间内如果有数据立刻响应请求; 如果时间到了还没有数据, 则响应 http 请求;浏览器受到 http 响应后立在发送一个同样http 请求查询是否有数据。这种交互的图例如下:
长轮询这种方式虽然能解决短轮询造成的过多Http请求,但是在等待的过程中,会一直保持着http的连接,影响浏览器端对服务器的http连接有最大限制,服务器端没有数据等待连接时会造成浪费, 容易产生服务器瓶颈,导致过多线程独占。如果要使用这种方式,最好同一用户只存在一个长轮询。
三、流技术( http streaming )
流技术是基于 Iframe 及 htmlfile 的流方式,Iframe是html标记,这个标记的src属性会保持对指定服务器的长连接请求,服务器端则可以不停地返回数据,相对于长连接,这种方式跟传统的服务器推则更接近。在长连接中,浏览器在收到数据后会直接调用JS回调函数,如 “<script type="text/javascript">函数名(返回数据)</script>”。当接收到服务器返回的页面元素,浏览器会执行页面的js函数,并将返回的数据作为回调函数的参数。
这种方式的局限性有一个明显不足之处:IE、Morzilla Firefox 下端的进度栏都会显示加载没有完成,而且 IE 上方的图标会不停的转动,表示加载正在进行。Google 使用一个称为“htmlfile”的 ActiveX 解决了在 IE 中的加载显示问题。
四、http 长连接( Server-Sent Event)
SSE(Server-Sent Event,服务端推送事件)是一种允许服务端向客户端推送新数据的HTML5技术。目前http协议普遍使用的是 1.1 版本,这个版本支持 http长连接。 http 长连接就是多个http请求共用一个tcp连接; 这样可以减少多次临近 http 请求导致 tcp建立关闭所产生的时间消耗。http 1.1中在请求头和相应头中用connection字段标识是否是 http长连接, connection: keep-alive, 表明是 http 长连接; connection:closed, 表明服务器关闭 tcp 连接与connection对应的一个字段是keep-live, http响应头中出现, 他的格式是timeout=30,max=5, timeout是两次 http 请求保持的时间(s), max 是这个tcp 连接最多为几个 http请求重用。
http 长连接局限性,SSE是单向通道,只能服务器向浏览器端发送。SSE不支持CORS 参数url就是服务器网址,必须与当前网页的网址在同一个网域(domain),而且协议和端口都必须相同。
五、Websocket
WebSocket protocol 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。它实现了浏览器与服务器全双工通信(full-duplex)。一开始的握手需要借助HTTP请求完成。Websocket可以理解为网络架构应用层的协议。
(一)WebSocket与HTTP的关系
相同点
1. 都是一样基于TCP的,都是可靠性传输协议。
2. 都是应用层协议。
不同点
1. WebSocket是双向通信协议,模拟Socket协议,可以双向发送或接受信息。HTTP是单向的。
2. WebSocket是需要握手进行建立连接的。
联系
WebSocket在建立握手时,数据是通过HTTP传输的。但是建立之后,在真正传输时候是不需要HTTP协议的。
(二)WebSocket与Socket的关系
Socket其实并不是一个协议,而是为了方便使用TCP或UDP而抽象出来的一层,是位于应用层和传输控制层之间的一组接口。
Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
当两台主机通信时,必须通过Socket连接,Socket则利用TCP/IP协议建立TCP连接。TCP连接则更依靠于底层的IP协议,IP协议的连接则依赖于链路层等更低层次。
WebSocket则是一个典型的应用层协议。
区别:Socket是传输控制层协议,WebSocket是应用层协议。
(三)HTML5与WebSocket的关系
WebSocket API 是 HTML5 标准的一部分, 但这并不代表 WebSocket 一定要用在 HTML 中,或者只能在基于浏览器的应用程序中使用。
实际上,许多语言、框架和服务器都提供了 WebSocket 支持,例如:
* 基于 C 的 libwebsocket.org
* 基于 Node.js 的 Socket.io
* 基于 Python 的 ws4py
* 基于 C++ 的 WebSocket++
* Apache 对 WebSocket 的支持: Apache Module mod_proxy_wstunnel
* Nginx 对 WebSockets 的支持: NGINX as a WebSockets Proxy 、 NGINX Announces Support for WebSocket Protocol 、WebSocket proxying
* lighttpd 对 WebSocket 的支持:mod_websocket
如果想使用Websocket有哪些限制呢?
(一)哪些中间件支持Websocket
(二)哪些浏览器支持Websocket
(三)Java开发的限制
Websocket 是servlet 3.1的技术,jdk7 才提供实现,jdk6 需要依赖第三方库才能实现。Websocket虽然有很多的限制,但是对于移动互联网的当今社会,他俨然有很多的使用场景,能够成为主流的技术要求。
总结:
从兼容性角度考虑,短轮询>长轮询>长连接SSE>WebSocket。
从性能方面考虑,WebSocket>长连接SSE>长轮询>短轮询。
Websocket基于TCP实现双向通信。
Websocket有着更广阔的使用场景需要设计人员深入的挖掘。
网友评论