H5:webSocket详解
websocket是html5规范中的一部分,客户端新建一个websocket实例.绑定需要连接到的服务器,当客户端连接服务端的时候,会向服务端发送一个http报文,如果服务端支持websocket协议,那么它就会将自己的通信协议切换到websocket,同时发给客户端响应报文头:
服务端响应报文头
返回的状态码为101,表示同意客户端协议转换请求,并将它转换为websocket协议。以上过程都是利用http通信完成的,称之为websocket协议握手(websocket Protocol handshake),进过这握手之后,客户端和服务端就建立了websocket连接,以后的通信走的都是websocket协议了。所以总结为websocket握手需要借助于http协议,建立连接后通信过程使用websocket协议。同时需要了解的是,该websocket连接还是基于我们刚才发起http连接的那个TCP连接。一旦建立连接之后,我们就可以进行数据传输了,websocket提供两种数据传输:文本数据和二进制数据。
详细用法参考webIm项目。
刨根问底HTTP和WebSocket协议(二)
上篇介绍了HTTP1.1协议的基本内容,这篇文章将继续分析WebSocket协议,然后对这两个进行简单的比较。
WebSocket协议还很年轻,RFC文档相比HTTP的发布时间也很短,它的诞生是为了创建一种「 双向通信 」的协议,来作为HTTP协议的一个替代者。那么首先看一下它和HTTP(或者HTTP的长连接)的区别。
上一篇中提到WebSocket的目的就是解决网络传输中的双向通信的问题,HTTP1.1默认使用持久连接(persistent connection),在一个TCP连接上也可以传输多个Request/Response消息对,但是HTTP的基本模型还是一个Request对应一个Response。这在双向通信(客户端要向服务器传送数据,同时服务器也需要实时的向客户端传送信息,一个聊天系统就是典型的双向通信)时一般会使用这样几种解决方案:
WebSocket的目的是取代HTTP在双向通信场景下的使用,而且它的实现方式有些也是基于HTTP的(WS的默认端口是 80 和 443 )。现有的网络环境(客户端、服务器、网络中间人、代理等)对HTTP都有很好的支持,所以这样做可以充分利用现有的HTTP的基础设施,有点向下兼容的意味。
简单来讲,WS协议有两部分组成:握手和数据传输。
出于兼容性的考虑,WS的握手使用HTTP来实现(此文档中提到未来有可能会使用专用的端口和方法来实现握手),客户端的握手消息就是一个「普通的,带有Upgrade头的,HTTP Request消息」。所以这一个小节到内容大部分都来自于RFC2616,这里只是它的一种应用形式,下面是RFC6455文档中给出的一个客户端握手消息示例:
可以看到,前两行跟HTTP的Request的起始行一模一样,而真正在WS的握手过程中起到作用的是下面几个header域。
如果服务器接受了这个请求,可能会发送如下这样的返回信息,这是一个标准的HTTP的Response消息。 101 表示服务器收到了客户端切换协议的请求,并且同意切换到此协议。RFC2616规定只有切换到的协议「比HTTP1.1更好」的时候才能同意切换。
ws协议默认使用 80 端口,wss协议默认使用 443 端口。
在握手之前,客户端首先要先建立连接,一个客户端对于一个相同的目标地址(通常是域名或者IP地址,不是资源地址)同一时刻只能有一个处于CONNECTING状态(就是正在建立连接)的连接。从建立连接到发送握手消息这个过程大致是这样的:
如果客户端没有处于代理环境中,它就要首先建立一个到达目标地址的直接的TCP连接。
服务端指的是所有参与处理WebSocket消息的基础设施,比如如果某服务器使用Nginx(A)来处理WebSocket,然后把处理后的消息传给响应的服务器(B),那么A和B都是这里要讨论的服务端的范畴。
如果请求是HTTPS,则首先要使用TLS进行握手,如果失败,则关闭连接,如果成功,则之后的数据都通过此通道进行发送。
之后服务端可以进行一些客户端验证步骤(包括对客户端header域的验证),如果需要,则按照RFC2616来进行错误码的返回。
如果一切都成功,则返回成功的Response握手消息。
此握手消息是一个标准的HTTP Response消息,同时它包含了以下几个部分:
一旦这个握手发出去,服务端就认为此WebSocket连接已经建立成功,处于OPEN状态。它就可以开始发送数据了。
Sec-WebSocket-Version可以被通信双方用来支持更多的协议的扩展,RFC6455中定义的值为 13 ,WebSocket的客户端和服务端可能回自定义更多的版本号来支持更多的功能。其使用方法如上文所述。
WebSocket中所有发送的数据使用帧的形式发送。客户端发送的数据帧都要经过掩码处理,服务端发送的所有数据帧都不能经过掩码处理。否则对方需要发送关闭帧。
一个帧包含一个帧类型的标识码,一个负载长度,和负载。负载包括扩展内容和应用内容。
帧类型是由一个4位长的叫Opcode的值表示,任何WebSocket的通信方收到一个位置的帧类型,都要以连接失败的方式断开此连接。
RFC6455中定义的帧类型如下所示:
具体的每一项代表什么意思在这里就不做详细的阐述了。
同样作为应用层的协议,WebSocket在现代的软件开发中被越来越多的实践,和HTTP有很多相似的地方,这里将它们简单的做一个纯个人、非权威的比较:
这一篇简单地将WebSocket协议介绍了一遍,篇幅有点长了,数据帧也没有来得及详述。下篇会继续深扒WebSocket帧传输,另外将通过实例探讨一些WebSocket协议实际使用中的问题。
刨根问底HTTP和WebSocket协议(一)
WebSocket和Socket的区别(WebSocket外传)
刨根问底HTTP和WebSocket协议(三)
websocket协议详解
相较于HTTP协议,HTTP协议有一个的缺陷为:通信只能由客户端发起。在一些场景下,这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦。我们只能使用轮询:每隔一段时候,就发出一个询问,了解服务器有没有新的信息。最典型的场景就是聊天室。
轮询的效率低,非常浪费资源(因为必须不停连接,或者 HTTP 连接始终打开)。因此,工程师们一直在思考,有没有更好的方法。WebSocket 就是这样发明的。
Webscoket是Web浏览器和服务器之间的一种全双工通信协议,其中WebSocket协议由IETF定为标准,WebSocket API由W3C定为标准。一旦Web客户端与服务器建立起连接,之后的全部数据通信都通过这个连接进行。通信过程中,可互相发送JSON、XML、HTML或图片等任意格式的数据。
WebSocket协议-原理篇
本篇文章主要讲述以下几点:
WebSocket协议分为两部分:握手和数据传输
下面通过客户端和服务端交互的报文对比WebSocket通讯与传统HTTP的不同点,主要关注握手阶段。
根据上面的例子,运行之后,new WebSocket实例化一个新的WebSocket客户端对象,请求WebSocket URL为 ws://localhost:8000 的服务器,打开控制台的NetWork,客户端WebSocket对象会自动解析并识别为WebSocket请求,连接服务端端口,执行双方握手过程,来自客户端握手发送数据格式如下:
至此,HTTP已经完成它所有工作,接下来就是完全按照Websocket协议进行了。
通过查看WebSocket的原理,与HTTP对比,得出结论:
HTTP长连接中,每次数据交换除了真正的数据部分外,服务器和客户端还要大量交换HTTP header,信息交换效率很低。Websocket协议通过第一个请求建立了TCP连接之后,之后交换的数据都不需要发送 HTTP header就能交换数据,这显然和原有的HTTP协议有区别,所以它需要对服务器和客户端都进行升级才能实现(主流浏览器都已支持HTML5)。此外还有 multiplexing、不同的URL可以复用同一个WebSocket连接等功能。这些都是HTTP长连接不能做到的。
我们在使用WebSocket协议时通常不会使用它的API来实现,而是借助于Socket.io,Socket.io是一个WebSocket库,包括客户端的js和服务端的nodejs,它的目标是构建可以在不同浏览器和移动设备上使用的实时应用。它会自动根据浏览器从WebSocket、AJAX长轮询等各种方式中选择最佳的方式来实现网络实时应用,也就是说如果浏览器对WebSocket兼容性差,Socket.io会自动选择最佳方式实现实时通信,非常方便和人性化。
Socket.io 官方文档:
WebSocket兼容几乎所有现代浏览器,IE 10+ Edge Firefox 4+ Chrome 4+ Safari 5+ Opera 11.5+
socket.io对浏览器做了很好的兼容。
下一篇讲述Socket.io客户端API
参考文档: