[关闭]
@xiaoyixy 2017-08-03T15:29:27.000000Z 字数 4245 阅读 1330

WebSocket

WebAPI


WebAsocket
WebSocket 对象提供了一组用于创建和管理 WebSocket 连接,以及可以通过该连接发送和接收数据的 API。WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

  1. 构造器 ->
    WebSocket WebSocket(in DOMString url, in optional DOMString protocols);
    WebSocket WebSocket(in DOMString url,in optional DOMString[] protocols);
    
    url 表示要连接的 URL。这个 URL 应该为响应 WebSocket 的地址。
    protocols [可选] 可以是一个单个的协议名字字符串或者包含多个协议名字字符串的数组。
    可能抛出以下异常 -> 
        SECURITY_ERR 试图连接的端口被屏蔽。
  2. readyState 常量:
    常量            值          描述
    CONNECTING      0           连接还没开启。
    OPEN            1           连接已开启并准备好进行通信。
    CLOSING         2           连接正在关闭的过程中。
    CLOSED          3           连接已经关闭,或者连接无法建立
  3. WebSocket.close() -> 关闭 WebSocket 连接或停止正在进行的连接请求。如果连接的状态已经是 closed,这个方法不会有任何效果
    void close(in optional unsigned short code, in optional DOMString reason);
    
    code [可选] 一个数字值表示关闭连接的状态号,表示连接被关闭的原因。如果这个参数没有被指定,默认的取值是 1000 (表示正常连接关闭)。 请看 CloseEvent 页面的 list of status codes 来看默认的取值。
    reason [可选] 一个可读的字符串,表示连接被关闭的原因。这个字符串必须是不长于 123 字节的 UTF-8 文本(不是字符)。
    可能抛出的异常 ->
        INVALID_ACCESS_ERR 选定了无效的 code([CloseEvent.code][1])。
        SYNTAX_ERR reason 字符串太长或者含有 unpaired surrogates。
  4. WebSocket.send() -> 通过 WebSocket 连接向服务器发送数据。
    void send(in DOMString data);
    void send(in ArrayBuffer data);
    void send(in Blob data); 
    
    data 要发送到服务器的数据。
    可能抛出的异常 -> 
        INVALID_STATE_ERR 当前连接的状态不是 OPEN。
        SYNTAX_ERR 数据是一个包含 unpaired surrogates 的字符串
    // 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);
    });
  5. HTML5 中的 WebSocket
    • HTML5定义了 WebSocket 协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。Websocket 使用 ws 或 wss 的统一资源标志符,类似于 HTTPS,其中 wss 表示在 TLS 之上的 Websocket。Websocket 使用和 HTTP 相同的 TCP 端口,可以绕过大多数防火墙的限制。默认情况下,Websocket 协议使用 80 端口;运行在 TLS 之上时,默认使用 443 端口
    • 握手协议 -> WebSocket 是独立的、创建在 TCP 上的协议。Websocket 通过 HTTP/1.1 协议101 状态码进行握手。为了创建Websocket连接,需要通过浏览器发出请求,之后服务器进行回应,这个过程通常称为“握手”(handshaking)。一个典型的Websocket握手请求如下:
      客户端请求
      GET / HTTP/1.1
      Upgrade: websocket
      Connection: Upgrade
      Host: example.com
      Origin: http://example.com
      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-Location: ws://example.com/
      
      - Connection 必须设置 Upgrade,表示客户端希望连接升级。
      - Upgrade 字段必须设置 Websocket,表示希望升级到 Websocket 协议。
      - Sec-WebSocket-Key 是随机的字符串,服务器端会用这些数据来构造出一个 SHA-1 的信息摘要。把 “Sec-WebSocket-Key” 加上一个特殊字符串 “258EAFA5-E914-47DA-95CA-C5AB0DC85B11”,然后计算 SHA-1 摘要,之后进行 BASE-64 编码,将结果做为 “Sec-WebSocket-Accept” 头的值,返回给客户端。如此操作,可以尽量避免普通 HTTP 请求被误认为 Websocket 协议。
      - Sec-WebSocket-Version 表示支持的 Websocket 版本。RFC6455 要求使用的版本是 13,之前草案的版本均应当被弃用。
      - Origin 字段是可选的,通常用来表示在浏览器中发起此 Websocket 连接所在的页面,类似于 Referer。但是,与 Referer 不同的是,Origin 只包含了协议和主机名称。
      - 其他一些定义在 HTTP 协议中的字段,如 Cookie 等,也可以在Websocket中使用。
  6. 兼容性
    • -> 基于 Gecko 6 – 10 版本的浏览器的 WebSocket 对象为 “MozWebSocket”,需要添加额外的代码。
    • -> 如果客户端不支持 WebSocket, 那么可以使用几个候选选项 Flash Socket AJAX long-polling AJAX multipart streaming IFrame JSONP polling
    • -> 使用Socket.io。该接口可以在浏览器不支持 WebSocket 的时候, 自动用浏览器支持的消息推送方式进行连接, 该库还会检测连接是否掉线,并在掉线时自动为你重新连接。
      // Create a Socket.io and its connection.
      var socket = new io.Socket('localhost',{port: 8080,});
      socket.connect();
      // Listen for connection.
      socket.on('connect',function(){
        console.log('Client has connected to the server!');
      });
      // Listen for messages.
      socket.on('message',function(data){
        console.log('Received a message from the server!',data);
      });
      // Listen for disconnection.
      socket.on('disconnect',function(){
        console.log('The client has disconnected!');
      });
      // Send a message.
      socket.send(message);
      
      
  7. 与服务器通信
    服务器建立连接后(启动 open 事件时),我们可以开始对连接对象使用 send('your message') 方法,向服务器发送数据。该方法以前只支持字符串,但根据最新的规范,现在也可以发送二进制讯息了。要发送二进制数据,您可以使用 Blob 或 ArrayBuffer 对象。
    // Sending String.
    connection.send('your message');
    
    // Sending canvas ImageData as ArrayBuffer.
    var img = canvas_context.getImageData(0, 0, 400, 320);
    var binary = new Uint8Array(img.data.length);
    for (var i = 0; i < img.data.length; i++) {
      binary[i] = img.data[i];
    }
    connection.send(binary.buffer);
    
    // Sending file as Blob.
    var file = document.querySelector('input[type="file"]').files[0];
    connection.send(file);
    
    服务器也可能随时向我们发送讯息。只要发生这种情况,就会启动 onmessage 回调。该回调接收的是事件对象,而实际的讯息可通过 data 属性进行访问。 在最新规范中,WebSocket 也可以接收二进制讯息。接收的二进制帧可以是 Blob 或 ArrayBuffer 格式。要指定收到的二进制数据的格式,可将 WebSocket 对象的 binaryType 属性设为“blob”或“arraybuffer”。默认格式为“blob”(您不必在发送时校正 binaryType 参数)。
    // Setting binaryType to accept received binary as either 'blob' or 'arraybuffer'
    connection.binaryType = 'arraybuffer';
    connection.onmessage = function(e) {
      console.log(e.data.byteLength); // ArrayBuffer object if binary
    };
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注