您的位置:首页 > 其它

Websocket协议概念、技术背景和原理介绍

2016-09-10 10:00 423 查看
WebSocket是什么

WebSocket技术背景
Comet

长链接
长连接的优势

长连接的劣势

长连接在Web浏览器中的使用

WebSocket优点

WebSocket的握手协议

WebSocket例子

WebSocket原理

浏览器

服务器

WebSocket是什么

WebSocket一种在单个 TCP 连接上进行全双工通讯的协议。WebSocket通信协议于2011年被IETF定为标准RFC 6455,并被RFC7936所补充规范,WebSocketAPI被W3C定为标准。

WebSocket 是独立的、创建在 TCP 上的协议,和 HTTP 的唯一关联是使用 HTTP 协议的101状态码进行协议切换,使用的 TCP 端口是80,可以用于绕过大多数防火墙的限制。

WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端直接向客户端推送数据而不需要客户端进行请求,在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并允许数据进行双向传送。

目前常见的浏览器如 Chrome、IE、Firefox、Safari、Opera 等都支持 WebSocket,同时需要服务端程序支持 WebSocket

WebSocket技术背景

现在,很多网站为了实现推送技术,所用的技术都是轮询。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP request,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP request的header是非常长的,里面包含的数据可能只是一个很小的值,这样会占用很多的带宽和服务器资源。



图1 HTTP request Headers


而比较新的技术去做轮询的效果是Comet,使用了AJAX。但这种技术虽然可达到双向通信,但依然需要发出请求,而且在Comet中,普遍采用了长链接,这也会大量消耗服务器带宽和资源。

面对这种状况,HTML5定义了WebSocket协议,能更好的节省服务器资源和带宽并达到实时通讯。目前chrome、Firefox、Opera、Safari等主流版本均支持,Internet Explorer从10开始支持。

针对上面提到的Comet和长连接的概念做一个说明:

Comet

Comet是一种用于web的推送技术,能使服务器实时地将更新的信息传送到客户端,而无须客户端发出请求,目前有两种实现方式,长轮询和iframe流。

长轮询

长轮询是在打开一条连接以后保持,等待服务器推送来数据再关闭的方式。

iframe流

iframe流方式是在页面中插入一个隐藏的iframe,利用其src属性在服务器和客户端之间创建一条长链接,服务器向iframe传输数据(通常是HTML,内有负责插入信息的javascript),来实时更新页面。

iframe流方式的优点是浏览器兼容好,Google公司在一些产品中使用了iframe流,如Google Talk。

长链接

HTTP持久连接(HTTP persistent connection,也称作HTTP keep-alive或HTTP connection reuse)是使用同一个TCP连接来发送和接收多个HTTP请求/应答,而不是为每一个新的请求/应答打开新的连接的方法。

在 HTTP 1.0 中, 没有官方的 keepalive 的操作。通常是在现有协议上添加一个指数。如果浏览器支持 keep-alive,它会在请求的包头中添加:

Connection: Keep-Alive

然后当服务器收到请求,作出回应的时候,它也添加一个头在响应中:

Connection: Keep-Alive



图2  请求响应 Connection: Keep-Alive参数


这样做,连接就不会中断,而是保持连接。当客户端发送另一个请求时,它会使用同一个连接。这一直继续到客户端或服务器端认为会话已经结束,其中一方中断连接。

在 HTTP 1.1 中 所有的连接默认都是持续连接,除非特殊声明不支持。HTTP 持久连接不使用独立的 keepalive 信息,而是仅仅允许多个请求使用单个连接。然而, Apache 2.0 httpd 的默认连接过期时间 是仅仅15秒,对于 Apache 2.2 只有5秒。短的过期时间的优点是能够快速的传输多个web页组件,而不会绑定多个服务器进程或线程太长时间。

长连接的优势

较少的CPU和内存的使用(由于同时打开的连接的减少了)

允许请求和应答的HTTP管线化

降低网络阻塞 (TCP连接减少了)

减少了后续请求的延迟(无需再进行握手)

报告错误无需关闭TCP连接

根据RFC 2616 (47页),用户客户端与任何服务器和代理服务器之间不应该维持超过2个链接。代理服务器应该最多使用2×N个持久连接到其他服务器或代理服务器,其中N是同时活跃的用户数。这个指引旨在提高HTTP响应时间并避免阻塞。

长连接的劣势

对于现在的广泛普及的宽带连接来说,Keep-Alive也许并不像以前一样有用。web服务器会保持连接若干秒(Apache中默认15秒),这与提高的性能相比也许会影响性能。对于单个文件被不断请求的服务(例如图片存放网站),Keep-Alive可能会极大的影响性能,因为它在文件被请求之后还保持了不必要的连接很长时间。

长连接在Web浏览器中的使用

网景导航者(4.05版本以后)和Internet Explorer(4.01版本以后)支持使用持久链接链接Web服务器和代理服务器。

网景不使用过时时间来关闭持久连接。而是对所有空闲的持久链接进行排队。当需要打开一个新的持久链接,但连接到不同的服务器上时,浏览器使用最近最少使用算法终止一个空闲的持久链接。

Internet Explorer支持持久链接,IE 6和IE 7缺省使用2个持久链接,而IE 8缺省使用6个持久链接。持久链接在不活跃60秒后过时,可以在Windows注册表中修改。

Mozilla Firefox支持持久链接。可以定制同时的持久连接的最大个数(每个服务器,每个代理服务器,总数)。连接在不活跃300秒(5分钟)后过时(配置中可以修改)。

Opera 4.0版本开始支持持久链接. 可以配置同时的持久连接的最大个数(每个服务器,总数)。



图3  使用多个连接和使用持久链接的对比


WebSocket优点

Header

服务器与客户端之间交换的数据包档头很小,大概只有2字节。(早期版本7.0)

服务器推送

服务器可以主动传送数据给客户端。

WebSocket的握手协议

在实现websocket连线过程中,需要透过浏览器发出websocket连线请求,然后服务器发出回应,这个过程通常称为“握手”(handshaking)。后期的版本大多属于功能上的扩充,例如使用第7版的握手协议同样也适用于第8版的握手协议。

WebSocket例子

为第13版且浏览器为Chrome的例子

浏览器请求:

GET / HTTP/1.1

Upgrade: websocket

Connection: Upgrade

Host: example.com

Origin: null

Sec-WebSocket-Key: sN9cRrP/n9NdMgdcy2VJFQ==

Sec-WebSocket-Version: 13

服务器回应:

HTTP/1.1 101 Switching Protocols

Upgrade: websocket

Connection: Upgrade

Sec-WebSocket-Accept: fFBooB7FAkLlXgRSz0BT3v4hq5s=

Sec-WebSocket-Origin: null

Sec-WebSocket-Location: ws://example.com/

WebSocket原理

”Upgrade:WebSocket”表示这是一个特殊的 HTTP 请求,请求的目的就是要将客户端和服务器端的通讯协议从 HTTP 协议升级到 WebSocket 协议。在请求中的“Sec-WebSocket-Key”是随机的,服务器端会用这些数据来构造出一个SHA-1的信息摘要。把“Sec-WebSocket-Key”加上一个魔幻字符串“258EAFA5-E914-47DA-95CA-C5AB0DC85B11”。使用SHA-1加密,之后进行BASE-64编码,将结果做为“Sec-WebSocket-Accept”头的值,返回给客户端。以表明服务器端获取了客户端的请求,同意创建 WebSocket 连接。一旦连接建立,客户端和服务器端就可以通过这个通道双向传输数据了。

浏览器

实现websocket的协议,浏览器扮演着一个很重要的角色。所有最新的浏览器支持最新规范(RFC 6455)的WebSocket协议。一个详细的测试报告列出了这些浏览器支持的Websocket版本。



图4 浏览器支持现状


基于Gecko 6–10版本的浏览器的WebSocket对象为“mozwebsocket”,需要添加额外的代码。

服务器

在服务器方面,网上都有不同对websocket支持的服务器:

php - http://code.google.com/p/phpwebsocket/

jetty - http://jetty.codehaus.org/jetty/(版本7开始支持websocket)

netty - http://www.jboss.org/netty

ruby - http://github.com/gimite/web-socket-ruby

Kaazing - http://www.kaazing.org/confluence/display/KAAZING/Home

Tomcat - http://tomcat.apache.org/(7.0.27支持websocket,建议用tomcat8,7.0.27中的接口已经过时)

WebLogic - http://www.oracle.com/us/products/middleware/cloud-app-foundation/weblogic/overview/index.html(12.1.2开始支持)

node.js - https://github.com/Worlize/WebSocket-Node

node.js - http://socket.io

nginx - http://nginx.com/

mojolicious - http://mojolicio.us/

python - https://github.com/abourget/gevent-socketio

Django - https://github.com/stephenmcd/django-socketio

erlang - https://github.com/ninenines/cowboy.git
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: