aboutsummaryrefslogtreecommitdiff
path: root/files/zh-cn/web/api/websockets_api/writing_websocket_client_applications
diff options
context:
space:
mode:
authorPeter Bengtsson <mail@peterbe.com>2020-12-08 14:40:17 -0500
committerPeter Bengtsson <mail@peterbe.com>2020-12-08 14:40:17 -0500
commit33058f2b292b3a581333bdfb21b8f671898c5060 (patch)
tree51c3e392513ec574331b2d3f85c394445ea803c6 /files/zh-cn/web/api/websockets_api/writing_websocket_client_applications
parent8b66d724f7caf0157093fb09cfec8fbd0c6ad50a (diff)
downloadtranslated-content-33058f2b292b3a581333bdfb21b8f671898c5060.tar.gz
translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.tar.bz2
translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.zip
initial commit
Diffstat (limited to 'files/zh-cn/web/api/websockets_api/writing_websocket_client_applications')
-rw-r--r--files/zh-cn/web/api/websockets_api/writing_websocket_client_applications/index.html186
1 files changed, 186 insertions, 0 deletions
diff --git a/files/zh-cn/web/api/websockets_api/writing_websocket_client_applications/index.html b/files/zh-cn/web/api/websockets_api/writing_websocket_client_applications/index.html
new file mode 100644
index 0000000000..c5fefb2336
--- /dev/null
+++ b/files/zh-cn/web/api/websockets_api/writing_websocket_client_applications/index.html
@@ -0,0 +1,186 @@
+---
+title: 编写WebSocket客户端应用
+slug: Web/API/WebSockets_API/Writing_WebSocket_client_applications
+tags:
+ - WebSocket
+ - 指南
+translation_of: Web/API/WebSockets_API/Writing_WebSocket_client_applications
+---
+<p>WebSocket客户端应用程序使用WebSocket API通过WebSocket协议与WebSocket服务器通信。</p>
+
+<p>{{AvailableInWorkers}}</p>
+
+<div class="warning">
+<p>本文中的示例代码片段来自我们的 WebSocket 聊天应用示例,<a href="https://github.com/mdn/samples-server/tree/master/s/websocket-chat">源代码在此处</a>,then <a href="https://mdn-samples.mozilla.org/s/websocket-chat">也可以在这里试一试</a>。现在示例中有一个 bug,使用不安全的 WebSockets 连接需要更新使用安全的 WebSocket,我们将很快修复。</p>
+</div>
+
+<h2 id="创建_WebSocket_对象">创建 WebSocket 对象</h2>
+
+<p>为了使用 WebSocket 协议通信,你需要创建一个 <a href="/en/WebSockets/WebSockets_reference/WebSocket" title="en/WebSockets/WebSockets reference/WebSocket"><code>WebSocket</code></a> 对象;这将会自动地尝试建立与服务器的连接。</p>
+
+<p>WebSocket 构造函数接受一个必要参数和一个可选参数:</p>
+
+<pre class="syntaxbox">WebSocket WebSocket(
+  in DOMString url,
+  in optional DOMString protocols
+);
+</pre>
+
+<dl>
+ <dt><code>url</code></dt>
+ <dd>要连接的URL;这应当是 WebSocket  服务器会响应的URL。</dd>
+ <dt><code>protocols</code> {{ optional_inline() }}</dt>
+ <dd>一个协议字符串或一个协议字符串数组。这些字符串用来指定子协议,这样一个服务器就可以实现多个WebSocket子协议(比如你可能希望一个服务器可以根据指定的 <code>protocol</code> 来应对不同的互动情况)。如果不指定协议字符串则认为是空字符串。</dd>
+</dl>
+
+<p>构造函数可能抛出以下异常:</p>
+
+<dl>
+ <dt><code>SECURITY_ERR</code></dt>
+ <dd>尝试连接的端口被阻塞。</dd>
+</dl>
+
+<dl>
+</dl>
+
+<h3 id="连接错误">连接错误</h3>
+
+<p>如果尝试连接过程中发生错误,那么首先一个名为 "error" 的事件会被发送给 <a href="/en/WebSockets/WebSockets_reference/WebSocket" title="WebSocket"><code>WebSocket</code></a> 对象(然后调用其<code>onerror</code> handler),然后 <a href="/en/WebSockets/WebSockets_reference/CloseEvent" title="CloseEvent"><code>CloseEvent</code></a> 被发送给<a href="/en/WebSockets/WebSockets_reference/WebSocket" title="WebSocket"><code>WebSocket</code></a>  (然后调用其 <code>onclose</code> handler)以说明连接关闭的原因。</p>
+
+<p>在 Firefox 11 中,通常会从 Mozilla 平台的控制台中收到一个描述性的错误信息,以及一个通过 <code><a href="/en/WebSockets/WebSockets_reference/CloseEvent" title="CloseEvent">CloseEvent</a></code> 在 <a class="external" href="http://tools.ietf.org/html/rfc6455#section-7.4" title="RFC 6455 Section 7.4">RFC 6455, Section 7.4</a> 中定义的错误代码。</p>
+
+<h3 id="示例">示例</h3>
+
+<p>本例创建了一个新的 WebSocket,连接到地址为 <code><span class="nowiki">ws://www.example.com/socketserver</span></code> 的服务器。请求中命名了一个自定义的协议 "protocolOne",这一部分可以省略。</p>
+
+<pre class="brush: js">var exampleSocket = new WebSocket("ws://www.example.com/socketserver", "protocolOne");
+</pre>
+
+<p>返回后,<code>exampleSocket.readyState</code> 参数为 <code>CONNECTING</code>。一旦连接可以传送数据,<code>readyState</code> 就会变成 <code>OPEN</code> 。</p>
+
+<p>如果你想建立一个支持协议可选的连接,你可以指定协议的列表:</p>
+
+<pre class="brush: js">var exampleSocket = new WebSocket("ws://www.example.com/socketserver", ["protocolOne", "protocolTwo"]);
+</pre>
+
+<p>一旦连接建立了(也就是说 <code>readyState</code> 是 <code>OPEN</code>) <code>exampleSocket.protocol</code> 就会告诉你服务器选择了哪个协议。</p>
+
+<p>上面的例子中 <code>ws</code> 替代了 <code>http</code>,同样地 <code>wss 也会替代https</code>. 建立WebSocket链接有赖于 <a href="/en-US/docs/Web/HTTP/Protocol_upgrade_mechanism">HTTP Upgrade mechanism</a>, 所以当我们使用 <code><span class="nowiki">ws://www.example.com</span></code>或者 <code><span class="nowiki">wss://www.example.com</span></code>来访问HTTP服务器的时候协议会隐式地升级。</p>
+
+<h2 id="向服务器发送数据">向服务器发送数据</h2>
+
+<p>一旦你的连接打开完成,你就可以向服务器发送数据了。对每一个要发送的消息使用 <code>WebSocket</code> 对象的 <a href="/en/WebSockets/WebSockets_reference/WebSocket#send()" title="en/WebSockets/WebSockets reference/WebSocket#send()"><code>send()</code></a> 方法:</p>
+
+<pre class="brush: js">exampleSocket.send("Here's some text that the server is urgently awaiting!");
+</pre>
+
+<p>你可以把数据作为字符串,{{ domxref("Blob") }},或者<a href="/en/JavaScript_typed_arrays/ArrayBuffer" title="en/JavaScript typed arrays/ArrayBuffer"><code>ArrayBuffer</code></a>来发送。</p>
+
+<div class="note"><strong>注意:</strong> 在版本11之前,Firefox只支持以字符串的形式发送数据。</div>
+
+<p>因为连接的建立是异步的,而且容易失败,所以不能保证刚创建WebSocket对象时使用 <code>send()</code> 方法会成功。我们至少可以确定企图在链接建立起来之后立马发送数据,可以通过注册 <code>onopen</code> 事件处理器解决:</p>
+
+<pre class="brush: js">exampleSocket.onopen = function (event) {
+  exampleSocket.send("Here's some text that the server is urgently awaiting!");
+};
+</pre>
+
+<h3 id="使用_JSON_发送对象">使用 JSON 发送对象</h3>
+
+<p>你可以方便地使用<a href="/en/JSON" title="en/JSON">JSON</a> 来向服务器发送复杂一些的数据。例如一个聊天程序与服务器交互的协议可以通过封装在JSON里的数据来实现:</p>
+
+<pre class="brush: js">// 服务器向所有用户发送文本
+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 = "";
+}
+</pre>
+
+<h2 id="接收服务器发送的消息">接收服务器发送的消息</h2>
+
+<p>WebSockets 是一个基于事件的 API;收到消息的时候,一个 "message" 消息会被发送到 <code>onmessage</code> 函数。为了开始监听传入数据,可以进行如下操作:</p>
+
+<pre class="brush: js">exampleSocket.onmessage = function (event) {
+  console.log(event.data);
+}
+</pre>
+
+<h3 id="接受与解析_JSON_对象">接受与解析 JSON 对象</h3>
+
+<p>考虑在 {{ anch("Using JSON to transmit objects") }}中提到的聊天应用客户端。客户端会收到各种类型的数据包,比如:</p>
+
+<ul>
+ <li>登陆握手</li>
+ <li>消息文本</li>
+ <li>用户列表更新</li>
+</ul>
+
+<p>解析这些收到的消息的代码可能是这样的:</p>
+
+<pre><code>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 = "&lt;b&gt;User &lt;em&gt;" + msg.name + "&lt;/em&gt; signed in at " + timeStr + "&lt;/b&gt;&lt;br&gt;";
+ break;
+ case "message":
+ text = "(" + timeStr + ") &lt;b&gt;" + msg.name + "&lt;/b&gt;: " + msg.text + "&lt;br&gt;";
+ break;
+ case "rejectusername":
+ text = "&lt;b&gt;Your username has been set to &lt;em&gt;" + msg.name + "&lt;/em&gt; because the name you chose is in use.&lt;/b&gt;&lt;br&gt;"
+ break;
+ case "userlist":
+ var ul = "";
+ for (i=0; i &lt; msg.users.length; i++) {
+ ul += msg.users[i] + "&lt;br&gt;";
+ }
+ document.getElementById("userlistbox").innerHTML = ul;
+ break;
+ }
+
+ if (text.length) {
+ f.write(text);
+ document.getElementById("chatbox").contentWindow.scrollByPages(1);
+ }
+};</code></pre>
+
+<p>这里我们使用 <a href="/en/JavaScript/Reference/Global_Objects/JSON/parse" title="en/JavaScript/Reference/Global Objects/JSON/parse"><code>JSON.parse()</code></a> 来将JSON转换回原始对象,然后检查并根据其内容做下一步动作。</p>
+
+<h3 id="文本数据的格式">文本数据的格式</h3>
+
+<p>通过WebSocket连接收到的文本是 UTF-8 格式的。</p>
+
+<p>在 Gecko 9.0 {{ geckoRelease("9.0") }} 之前,一部分有效的 UTF-8 文本中的非字符将导致连接被中断。现在 Gecko 已经允许这些值。</p>
+
+<h2 id="关闭连接">关闭连接</h2>
+
+<p>当你不需要再用 WebSocket 连接了,调用 WebSocket <a href="/en/WebSockets/WebSockets_reference/WebSocket#close()" title="en/WebSockets/WebSockets reference/WebSocket#close()"><code>close()</code></a>方法:</p>
+
+<pre class="brush: js">exampleSocket.close();
+</pre>
+
+<p>关闭连接前最好检查一下 socket 的 <code>bufferedAmount</code> 属性,以防还有数据要传输。</p>
+
+<h2 id="安全方面的考虑">安全方面的考虑</h2>
+
+<p>WebSocket 不应当用于混合的上下文环境;也就是说,不应该在用HTTPS加载的页面中打开非安全版本的WebSocket,反之亦然。而实际上一些浏览器也明确禁止这一行为,包括 Firefox 8 及更高版本。</p>