• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • html5 全双工通讯(websocket)

    版本:HTML5

    WebSocket是HTML5开始提供的一种浏览器与服务器之间进行全双工通信的网路技术。在WebSocket中,浏览器只需要完成一次握手就可以形成一条通道,允许Client和Server进行数据的互传。

    WebSocket是HTML5开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。在WebSocket API中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。

    浏览器通过 JavaScript 向服务器发出建立 WebSocket 连接的请求,连接建立以后,客户端和服务器端就可以通过 TCP 连接直接交换数据。当你获取 Web Socket 连接后,你可以通过send()方法来向服务器发送数据,并通过onmessage事件来接收服务器返回的数据。

    HTTP瓶颈
    很多网站为了做到即时通讯,所用的技术都是轮询,轮询就是客户端在一定的时间向服务器发送request,等待服务器的响应。由于每次轮询客户端都会发送请求,请求报文的首部会被反复发送,这样就会占用资源。

    AJAX使用
    它是通过Javascript脚本语言的调用就能和服务器进行HTTP通信,通过这种手段就可以再已经加载完毕的页面上发起请求,只是更新局部页面。

    Comet使用
    一旦服务器有更新,Comet不会让请求等待,而是直接给客户端返回响应,这种是通过延迟应答模拟实现付武器向客户端推送的功能。服务器收到请求,在处理完后就立即返回响应,但是为了实现推送功能,Conet会把响应置于挂起状态,当服务器中内容有更新时,再返回响应。但是这样做会维持连接消耗更多的资源,所以仍没有解决HTTP协议本身的问题。

    WebSocket
    而WebSocket的出现,让问题有了好转,客户端仍然是采用HTTP协议与服务器进行通信,但是当三次握手后,客户端请求升级为WebSocket协议,如果服务器能支持就会升级协议为WebSocket,这样就建立了一个全双工的通信。注意,还是需要客户端来主动连接服务器才能进行后面的事。

    HTML5规范中,WebSocket提供了一个受欢迎的技术,以替代我们过去几年一直在用的Ajax技术。这个新的API提供了一个方法,从客户端使用简单的语法有效地推动消息到服务器。让我们看一看HTML5的WebSocket API:它可用于客户端、服务器端。而且有一个优秀的第三方API,名为Socket.IO。

    浏览器支持

    IE不支持

    WebSocket API

    WebSocket API是下一代客户端-服务器的异步通信方法。该通信取代了单个的TCP套接字,使用ws或wss协议,可用于任意的客户端和服务器程序。WebSocket目前由W3C进行标准化。WebSocket已经受到Firefox 4、Chrome 4、Opera 10.70以及Safari 5等浏览器的支持。

    WebSocket API最伟大之处在于服务器和客户端可以在给定的时间范围内的任意时刻,相互推送信息。WebSocket并不限于以Ajax(或XHR)方式通信,因为Ajax技术需要客户端发起请求,而WebSocket服务器和客户端可以彼此相互推送信息;XHR受到域的限制,而WebSocket允许跨域通信。

    Ajax技术很聪明的一点是没有设计要使用的方式。WebSocket为指定目标创建,用于双向推送消息。

    WebSocket对象

    WebSocket对象提供了用于创建和管理 WebSocket 连接,以及可以通过该连接发送和接收数据的 API。

    构造函数

    WebSocket(url[, protocols])

    返回一个 WebSocket 对象

    常量

    ConstantValue
    WebSocket.CONNECTING0
    WebSocket.OPEN1
    WebSocket.CLOSING2
    WebSocket.CLOSED3

    以上是WebSocket构造函数的原型中存在的一些常量,可通过 WebSocket.readyState 对照上述常量判断 WebSocket 连接当前所处的状态

    属性

    • WebSocket.binaryType:使用二进制的数据类型连接。
    • WebSocket.bufferedAmount只读。未发送至服务器的字节数。
    • WebSocket.extensions只读。服务器选择的扩展。
    • WebSocket.onclose:用于指定连接关闭后的回调函数。
    • WebSocket.onerror:用于指定连接失败后的回调函数。
    • WebSocket.onmessage:用于指定当从服务器接受到信息时的回调函数。
    • WebSocket.onopen:用于指定连接成功后的回调函数。
    • WebSocket.protocol只读。服务器选择的下属协议。
    • WebSocket.readyState只读。当前的链接状态。
    • WebSocket.url只读。WebSocket 的绝对路径。

    方法

    • WebSocket.close([code[, reason]]):关闭当前链接。
    • WebSocket.send(data):向服务器发送数据。

    示例

    // Create WebSocket connection.
    const socket = new WebSocket('ws://localhost:8080');
    // Connection opened
    socket.addEventListener('open', function (event) 
    {
        socket.send('Hello Server!');
    });
    // Listen for messages
    socket.addEventListener('message', function (event)
    {
        console.log('Message from server ', event.data);
    });
    


    只专注于客户端的API,因为每个服务器端语言有自己的API。下面的代码片段是打开一个连接,为连接创建事件监听器,断开连接,消息时间,发送消息返回到服务器,关闭连接。

    // 创建一个Socket实例
    var socket = new WebSocket('ws://localhost:8080'); 
    // 打开Socket 
    socket.onopen = function(event) 
    { 
      // 发送一个初始化消息
      socket.send('I am the client and I'm listening!'); 
      // 监听消息
      socket.onmessage = function(event) { 
        console.log('Client received a message',event); 
      }; 
      // 监听Socket的关闭
      socket.onclose = function(event) { 
        console.log('Client notified socket has closed',event); 
      }; 
      // 关闭Socket.... 
      //socket.close() 
    };
    

    让我们来看看上面的初始化片段。参数为URL,ws表示WebSocket协议。onopen、onclose和onmessage方法把事件连接到Socket实例上。每个方法都提供了一个事件,以表示Socket的状态。

    onmessage事件提供了一个data属性,它可以包含消息的Body部分。消息的Body部分必须是一个字符串,可以进行序列化/反序列化操作,以便传递更多的数据。

    WebSocket的语法非常简单,使用WebSockets是难以置信的容易……除非客户端不支持WebSocket。IE浏览器目前不支持WebSocket通信。如果你的客户端不支持WebSocket通信,下面有几个后备方案供你使用:

    • Flash技术—— Flash可以提供一个简单的替换。使用Flash最明显的缺点是并非所有客户端都安装了Flash,而且某些客户端,如iPhone/iPad,不支持Flash。
    • AJAX Long-Polling技术——用AJAX的long-polling来模拟WebSocket在业界已经有一段时间了。它是一个可行的技术,但它不能优化发送的信息。也就是说,它是一个解决方案,但不是最佳的技术方案。

    由于目前的IE等浏览器不支持WebSocket,要提供WebSocket的事件处理、返回传输、在服务器端使用一个统一的API,那么该怎么办呢?幸运的是,Guillermo Rauch创建了一个Socket.IO技术。

    带Socket.IO的WebSocket

    Socket.IO是Guillermo Rauch创建的WebSocket API,Guillermo Rauch是LearnBoost公司的首席技术官以及LearnBoost实验室的首席科学家。Socket.IO使用检测功能来判断是否建立WebSocket连接,或者是AJAX long-polling连接,或Flash等。可快速创建实时的应用程序。Socket.IO还提供了一个NodeJS API,它看起来非常像客户端API。

    建立客户端Socket.IO
    Socket.IO可以从GitHub下载,可以把socket.io.js文件包含到页面中:

    <script src="socket.io.js"></script>
    // 创建Socket.IO实例,建立连接
    var socket= new io.Socket('localhost',{ 
      port: 8080 
    }); 
    socket.connect(); 
    // 添加一个连接监听器
    socket.on('connect',function() { 
      console.log('Client has connected to the server!'); 
    });
    // 添加一个连接监听器
    socket.on('message',function(data) { 
      console.log('Received a message from the server!',data); 
    });
    // 添加一个关闭连接的监听器
    socket.on('disconnect',function() { 
      console.log('The client has disconnected!'); 
    }); 
    // 通过Socket发送一条消息到服务器
    function sendMessageToServer(message) { 
      socket.send(message); 
    }
    

    Socket.IO简化了WebSocket API,统一了返回运输的API。传输包括:
    WebSocket
    Flash Socket
    AJAX long-polling
    AJAX multipart streaming
    IFrame
    JSONP polling

    你还可以设置任意的Socket.IO构造器的第二个选项,选项包括:
    port -待连接的端口
    transports -一个数组,包含不同的传输类型
    transportOptions -传输的参数使用的对象,带附加属性

    Socket.IO还提供了由本地WebSocket API提供的普通连接、断开连接、消息事件。Socket还提供了封装每个事件类型的方法。