diff options
author | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:40:17 -0500 |
---|---|---|
committer | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:40:17 -0500 |
commit | 33058f2b292b3a581333bdfb21b8f671898c5060 (patch) | |
tree | 51c3e392513ec574331b2d3f85c394445ea803c6 /files/zh-cn/web/api/websockets_api/writing_websocket_client_applications | |
parent | 8b66d724f7caf0157093fb09cfec8fbd0c6ad50a (diff) | |
download | translated-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.html | 186 |
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 = "<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); + } +};</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> |