上一节已经说了很多Websocket的特点,它是一种建立在TCP协议上、与HTTP/HTTPS协议良好兼容网络协议;而且Websocket是一种双向通信协议,可以让浏览器和服务器之间相互发送、接收数据。
啥是“轮询”?这就要说起HTTP/HTTPS协议的单向性:通信请求只能由客户端浏览器发起。
举一个简单的例子,为了防止六大派进攻光明顶,于是在光明顶上建立了一个瞭望塔,当瞭望台可以记录方圆百里内的六大派敌人的数量(假设一个变量n,瞭望得到敌人的数量都会保存在这个变量n中),在六大派没有发起进攻时,这个n则会等于0。
当时的光明左使负责防御,他要根据敌人数量n这个值来进行部署,所以他(客户端)只能是每隔几秒钟通过HTTP/HTTPS请求来向瞭望塔(服务器)发起请求来询问获得当前n变量的值。这就是所谓的轮询。
轮询并不明智,只是限制于当时的方式方法。首先,轮询对瞭望塔(服务器)的资源造成大幅消耗浪费;而且轮询纵使间隔时间很短,但终究是有时间间隔的,即时性无法到达炉火纯青的境界。
后来,明教有新教主了,遂教大家用了一套新的神功大法,就是传说中的Websocket;有了Websocket这种协议,光明左使(客户端)只要用Websocket的方式连上瞭望塔(服务器),只要瞭望塔(服务器)发现新的六大派的敌人,瞭望塔(服务器)就会主动把此时的n值(敌人总数量)发送给刚才已经连上瞭望塔的光明左使(客户端)。
如此,不仅仅是性能开销小、通信更加即时;而且每次通信的数据量也变得更加轻量。因此,Websocket在六大派围攻光明顶一战中,为明教立下了汗马功劳。
Websocket协议最早出现于2008年,于2011年被IETF定为标准RFC 6455,并被RFC7936所补充规范。现在几乎所有的浏览器都支持Websocket协议;下表为各浏览器支持Websocket的最低版本:
API | ![]() |
![]() |
![]() |
![]() |
![]() |
---|---|---|---|---|---|
Websocket | 4.0 | 10.0 | 6.0 | 5.0 | 12.0 |
这里使用第三方网站提供的一个Websocket协议的接口( wss://echo.websocket.org )用来测试;第三方Websocket服务器端定的规则是客户端发送什么数据过去,服务器则返回同样的数据。示例比较简单,代码如下:
var ws = new WebSocket("wss://echo.websocket.org"); ws.onopen = function(event) { alert("连接连上咯~"); ws.send("为人民服务~"); }; ws.onmessage = function(event) { alert( "服务器发过来的数据是: " + event.data); ws.close(); }; ws.onclose = function(event) { alert("连接关闭了。"); };
上例中通过WebSocket类构造了一个WebSocket实例对象,即ws变量。
var ws = new WebSocket("wss://echo.websocket.org");
当用上述方法创建WebSocket实例时,客户端就会与服务器进行握手连接。而WebSocket实例对象常用的一些属性如下所示:
属性 | 说明 |
---|---|
readyState | 返回当前连接状态,共有4种状态 CONNECTING,值为0,表示正在连接; OPEN,值为1,表示连接握手成功,可以进行通信; CLOSING,值为2,表示连接正在关闭; CLOSED,值为3,表示连接已经关闭或连接失败。 |
bufferedAmount | 返回当前还剩多少字节的即将发送的二进制数据 用于判断发送是否结束(只读) |
url | 返回该Websocket请求的URL绝对地址(只读) 例如返回“wss://echo.websocket.org” |
binaryType | 返回二进制数据所使用的格式,有2种格式 blob(二进制大对象)、arraybuffer(二进制数组) |
onopen | 事件监听器 - 连接成功 |
onmessage | 事件监听器 - 收到服务器端发送信息 |
onclose | 事件监听器 - 连接断开 |
onerror | 事件监听器 - 发生错误 |
WebSocket实例对象的方法如下表所列:
方法 | 说明 |
---|---|
close([code[, reason]]) | 断开与服务器的连接 |
send(data) | 向已连接的服务器端发送数据 |
更多关于Websocket的属性和方法参考这里。
WebSocket实例对象的onopen属性可用于指定连接成功后的回调函数。
ws.onopen = function(event) { alert("连接连上咯~"); ws.send("为人民服务~"); };
也可通过addEventListener
方法进行添加,该方法的好处是可添加不止一个回调函数:
ws.addEventListener('open', function (event) { alert("连接连上咯~"); ws.send("为人民服务~"); });
WebSocket实例对象的onmessage属性可用于指定收到服务器端发送信息后的回调函数。
ws.onmessage = function(event) { alert( "服务器发过来的数据是: " + event.data); ws.close(); };
也可通过addEventListener
方法进行添加,该方法的好处是可添加不止一个回调函数:
ws.addEventListener('message', function (event) { alert( "服务器发过来的数据是: " + event.data); ws.close(); });
WebSocket实例对象的onclose属性可用于指定Websocket连接断开而触发的回调函数。
ws.onclose = function(event) { alert("连接关闭了。"); };
也可通过addEventListener
方法进行添加,该方法的好处是可添加不止一个回调函数:
ws.addEventListener('close', function (event) { alert("连接关闭了。"); });
WebSocket实例对象的send方法可向已握手连接的服务器发送数据:
ws.send( "为人民服务~" );
关于Websocket的服务器端:大部分服务器程序都会有实现Websocket的模块或者外部插件;在此推荐两款可以写Websocket服务器端的框架:Websocketd(后端开发语言没有限制) 和 Tornado(基于Python的Web服务器框架)