这篇翻译不完整。请帮忙从英语翻译这篇文章

WebSocket 是一种基于ws协议的技术。使用它可以在客户端与服务器之间建立一段连续的、全双工的连接。浏览器是一个典型的 WebSocket 客户端,但该协议是独立于平台的。

注意:We have a working example of the chat/server system used for code snippets that will be made available once our infrastructure is in place for hosting WebSocket examples properly.

Note: 此特性在 Web Worker 中可用。

创建 WebSocket 对象

为了使用 WebSocket 协议通信,你需要创建一个 WebSocket 对象;这将会自动地尝试建立与服务器的连接。

WebSocket 构造函数接受一个必要参数和一个可选参数:

WebSocket WebSocket(
  in DOMString url,
  in optional DOMString protocols
);
url
要连接的URL;这应当是 WebSocket  服务器会响应的URL。
protocols 可选
一个或多个协议字符串。这些字符串用来指定子协议,这样一个服务器就可以实现多个WebSocket子协议(比如你可能希望一个服务器可以根据指定的 protocol 来应对不同的互动情况)。如果不指定协议字符串则认为是空字符串。

构造函数可能抛出以下异常:

SECURITY_ERR
尝试连接的端口被阻塞。

连接错误

如果尝试连接过程中发生错误,那么首先一个名为 "error" 的事件会被发送给 WebSocket 对象(然后调用其onerror handler),然后 CloseEvent 被发送给WebSocket  (然后调用其 onclose handler)以说明连接关闭的原因。

As of Firefox 11 however, it is typical to receive a descriptive error message in the console from the Mozilla platform, and a closing code as defined in RFC 6455, Section 7.4 through the CloseEvent.

示例

本例创建了一个新的 WebSocket,连接到地址为 ws://www.example.com/socketserver 的服务器。请求中命名了一个自定义的协议 "protocolOne",这一部分可以省略。

var exampleSocket = new WebSocket("ws://www.example.com/socketserver", "protocolOne");

返回后,exampleSocket.readyState 参数为 CONNECTING。一旦连接可以传送数据,readyState 就会变成 OPEN 。

如果你想建立一个支持协议可选的连接,你可以指定协议的列表:

var exampleSocket = new WebSocket("ws://www.example.com/socketserver", ["protocolOne", "protocolTwo"]);

一旦连接建立了(也就是说 readyState 是 OPEN) exampleSocket.protocol 就会告诉你服务器选择了哪个协议。

上面的例子中 ws 替代了 http,同样地 wss 也会替代https. 建立WebSocket链接有赖于 HTTP Upgrade mechanism, 所以当我们使用 ws://www.example.com或者 wss://www.example.com来访问HTTP服务器的时候协议会隐式地升级。

向服务器发送数据

一旦你的连接打开完成,你就可以向服务器发送数据了。对每一个要发送的消息使用 WebSocket 对象的 send() 方法:

exampleSocket.send("Here's some text that the server is urgently awaiting!"); 

你可以把数据作为字符串,Blob,或者ArrayBuffer来发送。

注意: Prior to version 11, Firefox only supported sending data as a string.

因为连接的建立是异步的,而且容易失败,所以不能保证刚创建WebSocket对象时使用 send() 方法会成功。We can at least be sure that attempting to send data only takes place once a connection is established by defining an onopen handler to do the work:

exampleSocket.onopen = function (event) {
  exampleSocket.send("Here's some text that the server is urgently awaiting!"); 
};

使用 JSON 发送对象

你可以方便地使用JSON 来向服务器发送复杂一些的数据。例如一个聊天程序与服务器交互的协议可以通过封装在JSON里的数据来实现:

// 服务器向所有用户发送文本
function sendText() {
  // 构造一个 msg 对象, 包含了服务器处理所需的数据
  var msg = {
    type: "message",
    text: document.getElementById("text").value,
    id:   clientID,
    date: Date.now()
  };

  // 把 msg 对象作为JSON格式字符串发送
  exampleSocket.send(JSON.stringify(msg));
  
  // 清空文本输入元素,为接收下一条消息做好准备。
  document.getElementById("text").value = "";
} 

接收服务器发送的消息

WebSockets 是一个基于事件的 API;收到消息的时候,一个 "message" 消息会被发送到 onmessage 函数。为了开始监听传入数据,可以进行如下操作:

exampleSocket.onmessage = function (event) {
  console.log(event.data);
}

接受与解析 JSON 对象

考虑在 Using JSON to transmit objects中提到的聊天应用客户端。客户端会收到各种类型的数据包,比如:

  • 登陆握手
  • 消息文本
  • 用户列表更新

解析这些收到的消息的代码可能是这样的:

exampleSocket.onmessage = function(event) {
  var f = document.getElementById("chatbox").contentDocument;
  var text = "";
  var msg = JSON.parse(event.data);
  var time = new Date(msg.date);
  var timeStr = time.toLocaleTimeString();
  
  switch(msg.type) {
    case "id":
      clientID = msg.id;
      setUsername();
      break;
    case "username":
      text = "<b>User <em>" + msg.name + "</em> signed in at " + timeStr + "</b><br>";
      break;
    case "message":
      text = "(" + timeStr + ") <b>" + msg.name + "</b>: " + msg.text + "<br>";
      break;
    case "rejectusername":
      text = "<b>Your username has been set to <em>" + msg.name + "</em> because the name you chose is in use.</b><br>"
      break;
    case "userlist":
      var ul = "";
      for (i=0; i < msg.users.length; i++) {
        ul += msg.users[i] + "<br>";
      }
      document.getElementById("userlistbox").innerHTML = ul;
      break;
  }
  
  if (text.length) {
    f.write(text);
    document.getElementById("chatbox").contentWindow.scrollByPages(1);
  }
};

这里我们使用 JSON.parse() 来将JSON转换回原始对象,然后检查并根据其内容做下一步动作。

文本数据的格式

通过WebSocket连接收到的文本是 UTF-8 格式的。

在 Gecko 9.0 (Firefox 9.0 / Thunderbird 9.0 / SeaMonkey 2.6) 之前,certain non-characters in otherwise valid UTF-8 text would cause the connection to be terminated. Now Gecko permits these values.

关闭连接

当你不需要再用 WebSocket 连接了,调用 WebSocket close()方法:

exampleSocket.close();

关闭连接前最好检查一下 socket 的 bufferedAmount 属性,以防还有数据要传输。

安全方面的考虑

WebSocket 不应当用于混合的上下文环境;也就是说,不应该在用HTTPS加载的页面中打开非安全版本的WebSocket,反之亦然。而实际上一些浏览器也明确禁止这一行为,包括 Firefox 8 及更高版本。

文档标签和贡献者

标签: 
 此页面的贡献者: wubaodong, yydzxz, MegaThomas
 最后编辑者: wubaodong,