前端时间在做项目的时候遇到这样的一个场景:网页中有一个数据表格,这个数据表格数据表格的内容是从后台读取出来的,但是这些内容会随着时间的变化而变化,有点类似于股票行情。
当时我的做法是用setInterval('toPage(1)',1000)来定时执行函数,toPage()方法是通过ajax请求访问服务器,并在成功后拿到后台返回的数据然后去更新页面。
但是这种定时的方法有很多不足:
(1)频繁的网络请求对于客户端和服务器来说都是一种负担,比如当网页中出现多个定时器刷新页面的时候。
(2)如果服务器中没有更新数据,还是返回跟上一次一样的内容的话,这一次的定时任务时不必要的。
(3)如果服务器可能刚更新了数据,但是下一轮的定时任务还没有开始的话,页面内容可能就不够新。
而造成这些不足的原因归结起来,主要还是由于服务器的响应总是被动的,也就是http请求总是有客户端发起,再有服务端来返回响应数据。
websocket是html5开始提供的一种在单个TCP连接上进行双向通信的新协议,也就是说,客户端浏览器首先要向服务器发起一个http请求,这个请求和通常的http请求不同,包含了一些附加信息,比如:'Upgrade:websocket'表明这是一个申请协议升级的HTTP请求,服务端解析这些附加信息后返回响应消息给客户端,这样客户端和服务端的websocket连接就建立起来了,双方就可以自由的传递信息,并且这个连接会持续存在,直到双方的某一方主动的关闭连接。当你获取websocket连接后,你可以通过send()方法来向服务器发送数据,并通过onmessage事件来接收服务器返回的数据。
具体做法是:
(1)创建websocket对象
var Socket = new WebSocket(url, [protocol] );
* 第一个参数 url, 指定连接的 URL。
websocket的URL格式是ws://和wss://
wss://是加密通信
* 第二个参数 protocol 是可选的,指定了可接受的子协议。
例如:
var wsServer = 'ws://localhost:8080/Demo'; //服务器地址
var Socket = new WebSocket(wsServer); //创建WebSocket对象
Socket.readyState 表示连接状态 0: 表示连接尚未建立。 1:表示连接已建立,可以进行通信 2:表示连接正在进行关闭 3:表示连接已经关闭或者连接不能打开
(2)执行websocket相关事件
Socket.onopen 连接建立时触发 Socket.onmessage 客户端接收服务器数据时触发 Socket.onerror 通信发生错误时触发 Socket.onclose 连接关闭时触发
Socket.send() 使用连接发送数据 Socket.close() 关闭连接
实例如下:
function WebSocketTest(){ if ("WebSocket" in window) { alert("您的浏览器支持 WebSocket!"); // 打开一个 web socket var ws = new WebSocket("ws://localhost:8080/main"); ws.onopen = function(){ // Web Socket 已连接上,使用 send() 方法发送数据 ws.send("发送数据"); alert("数据发送中..."); }; ws.onmessage = function (evt) { var received_msg = evt.data; alert("数据已接收..."); }; ws.onclose = function() { // 关闭 websocket alert("连接已关闭..."); }; }else{ // 浏览器不支持 WebSocket alert("您的浏览器不支持 WebSocket!"); } }
http的生命周期通过request来界定,也就是一个request只能有一个response,而且这个response是被动的(服务端不能主动联系客户端,只能有客户端发起);另外http还是一个状态协议,也就是说每次都要重新传输鉴别信息来告诉服务器你是谁;
websocket是基于http协议的,只需要经过一次http请求,就可以做到消息传送了,也就是借用了http协议来完成一次握手后,服务端可以就可以主动推送消息给客户端。这个协议解决了传统http同步有延迟,而且非常消耗资源的问题。