<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body><section><h1>仕様書</h1><refs xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:"><ul xmlns="http://www.w3.org/1999/xhtml"><li><anchor-end xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:" a0:anchor="8" xmlns:a0="urn:x-suika-fam-cx:markup:suikawiki:0:9:">[8]</anchor-end> <cite xml:lang="en">RFC 6455 - The WebSocket Protocol</cite> (<time>2015-03-11 20:42:50 +09:00</time> 版) <anchor-external xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:" a0:resScheme="URI" xmlns:a0="urn:x-suika-fam-cx:markup:suikawiki:0:9:" a0:resParameter="http://tools.ietf.org/html/rfc6455#section-5.5.1">http://tools.ietf.org/html/rfc6455#section-5.5.1</anchor-external></li><li><anchor-end xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:" a0:anchor="11" xmlns:a0="urn:x-suika-fam-cx:markup:suikawiki:0:9:">[11]</anchor-end> <strong><cite xml:lang="en">RFC 6455 - The WebSocket Protocol</cite> (<time>2015-03-11 20:42:50 +09:00</time> 版) <anchor-external xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:" a0:resScheme="URI" xmlns:a0="urn:x-suika-fam-cx:markup:suikawiki:0:9:" a0:resParameter="http://tools.ietf.org/html/rfc6455#section-6">http://tools.ietf.org/html/rfc6455#section-6</anchor-external></strong></li><li><anchor-end xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:" a0:anchor="1" xmlns:a0="urn:x-suika-fam-cx:markup:suikawiki:0:9:">[1]</anchor-end> <cite xml:lang="en-GB-x-hixie">HTML Standard</cite> (<time>2015-05-06 10:42:35 +09:00</time> 版) <anchor-external xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:" a0:resScheme="URI" xmlns:a0="urn:x-suika-fam-cx:markup:suikawiki:0:9:" a0:resParameter="https://html.spec.whatwg.org/#dom-websocket-send">https://html.spec.whatwg.org/#dom-websocket-send</anchor-external></li></ul></refs></section><section><h1><code class="DOMi" xml:lang="en">WebSocket</code> インターフェイス <code class="DOMm" xml:lang="en">send</code> メソッド</h1><p><anchor-end xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:" a0:anchor="2" xmlns:a0="urn:x-suika-fam-cx:markup:suikawiki:0:9:">[2]</anchor-end> <code class="DOMi" xml:lang="en"><anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">WebSocket</anchor></code> <anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">インターフェイス</anchor>の
<dfn><code class="DOMm" xml:lang="en"><anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">send</anchor></code></dfn> <anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">メソッド</anchor>は、次のようにしなければ<anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:"><strong xmlns="http://www.w3.org/1999/xhtml">なりません</strong></anchor>
<src xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:10:"><anchor-internal xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:" a0:anchor="1" xmlns:a0="urn:x-suika-fam-cx:markup:suikawiki:0:9:">&gt;&gt;1</anchor-internal></src>。</p><figure class="steps"><ol><li>第1引数を <code class="DOMi" xml:lang="en"><anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">USVString</anchor></code>, <code class="DOMi" xml:lang="en"><anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">Blob</anchor></code>,
<code class="DOMi" xml:lang="en"><anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">ArrayBuffer</anchor></code>, <code class="DOMi" xml:lang="en"><anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">ArrayBufferView</anchor></code>
のいずれかとして解釈します。</li><li><code class="DOMa" xml:lang="en"><anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">readyState</anchor></code> が <code class="DOM" xml:lang="en"><anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">CONNECTING</anchor></code> なら、
<code class="DOMe" xml:lang="en"><anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">InvalidStateError</anchor></code> <anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">例外</anchor>を投げ、停止します。</li><li>第1引数が<anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">文字列</anchor>なら、<ol><li><var>データ</var>を、<anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">文字列</anchor>を <anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">UTF-8</anchor> <anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">符号化</anchor>したものに設定します。</li><li><var><anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">opcode</anchor></var> を、<anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">テキストフレーム</anchor> (<code><anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">1</anchor></code>) に設定します。</li></ol></li><li>第1引数が <code class="DOMi" xml:lang="en"><anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">Blob</anchor></code> なら、<ol><li><var>データ</var>を、 <code class="DOMi" xml:lang="en"><anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">Blob</anchor></code> が表現する生データに設定します。</li><li><var><anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">opcode</anchor></var> を、<anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">バイナリーフレーム</anchor> (<code><anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">2</anchor></code>) に設定します。</li></ol></li><li>第1引数が <code class="DOMi" xml:lang="en"><anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">ArrayBuffer</anchor></code> なら、<ol><li><var>データ</var>を、 <code class="DOMi" xml:lang="en"><anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">ArrayBuffer</anchor></code> のバッファーに蓄積されたデータに設定します。</li><li><var><anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">opcode</anchor></var> を、<anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">バイナリーフレーム</anchor> (<code><anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">2</anchor></code>) に設定します。</li></ol></li><li>第1引数が <code class="DOMi" xml:lang="en"><anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">ArrayBufferView</anchor></code> なら、<ol><li><var>データ</var>を、参照されている <code class="DOMi" xml:lang="en"><anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">ArrayBuffer</anchor></code> のバッファーに蓄積されたデータに設定します。</li><li><var><anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">opcode</anchor></var> を、<anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">バイナリーフレーム</anchor> (<code><anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">2</anchor></code>) に設定します。</li></ol></li><li>接続の状態が <code><anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">OPEN</anchor></code> なら、<ol><li><var>データ</var>、<var><anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">opcode</anchor></var> について<anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">WebSocketメッセージ送信</anchor>を行います。</li><li>失敗したら (例えば<anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">バッファー</anchor>が満杯なら)、<ol><li><anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">flagged as full</anchor> フラグを設定します。</li><li><anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">WebSocket接続を閉じる</anchor>処理を実行します。</li></ol></li></ol></li><li><code class="DOMa" xml:lang="en"><anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">bufferedAmount</anchor></code> に、<var>データ</var>のバイト数を<anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">加算</anchor>します。</li></ol></figure><comment-p xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:10:"><anchor-end xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:" a0:anchor="3" xmlns:a0="urn:x-suika-fam-cx:markup:suikawiki:0:9:">[3]</anchor-end> <code xmlns="http://www.w3.org/1999/xhtml" class="DOMa" xml:lang="en"><anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">bufferedAmount</anchor></code> は、送信されない場合でも増えていきます。</comment-p><comment-p xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:10:"><anchor-end xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:" a0:anchor="9" xmlns:a0="urn:x-suika-fam-cx:markup:suikawiki:0:9:">[9]</anchor-end> <anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">flagged as full</anchor> は、<anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">WebSocket接続が閉じられた</anchor>時に
<code xmlns="http://www.w3.org/1999/xhtml" class="DOMe" xml:lang="en"><anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">error</anchor></code> <anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">イベント</anchor>を<anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">発火</anchor>するかの判定に使われます。</comment-p></section><section><h1>処理</h1><p><anchor-end xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:" a0:anchor="12" xmlns:a0="urn:x-suika-fam-cx:markup:suikawiki:0:9:">[12]</anchor-end> <anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">WebSocket接続</anchor>において<dfn><rubyb xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">WebSocketメッセージ送信<rt xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">Send a WebSocket Message</rt></rubyb></dfn>するには、
次のようにしなければ<anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:"><strong xmlns="http://www.w3.org/1999/xhtml">なりません</strong></anchor> <src xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:10:"><anchor-internal xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:" a0:anchor="11" xmlns:a0="urn:x-suika-fam-cx:markup:suikawiki:0:9:">&gt;&gt;11</anchor-internal></src>。<figure class="steps"><ol><li>送信するデータを含む単一の<anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">フレーム</anchor>または<anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">断片化</anchor>された<anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">フレーム</anchor>群を作成します
(<anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">WebSocketフレーム</anchor>参照)。最初の<anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">フレーム</anchor>の <code><anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">opcode</anchor></code> は、
データの種別により、<anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">テキストフレーム</anchor>または<anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">バイナリーフレーム</anchor>とします。</li><li>送信元が<anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">クライアント</anchor>であれば、<anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">マスク</anchor>します (<anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">WebSocketフレーム</anchor>参照)。</li><li><anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">WebSocket拡張</anchor>を用いる場合は、その規定に従い適宜処理します。</li><li><anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">フレーム</anchor>(群)を転送します。</li></ol></figure></p><p><anchor-end xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:" a0:anchor="13" xmlns:a0="urn:x-suika-fam-cx:markup:suikawiki:0:9:">[13]</anchor-end> <anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">データフレーム</anchor>を <anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:"><code xmlns="http://www.w3.org/1999/xhtml">Close</code>フレーム</anchor>より後に送っては<anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:"><strong xmlns="http://www.w3.org/1999/xhtml">なりません</strong></anchor>
<src xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:10:"><anchor-internal xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:" a0:anchor="7" xmlns:a0="urn:x-suika-fam-cx:markup:suikawiki:0:9:">&gt;&gt;7</anchor-internal></src>。
<anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">WebSocket接続</anchor>の状態が <code><anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">OPEN</anchor></code> でなければ (なくなれば)、
この手順は停止しなければ<anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:"><strong xmlns="http://www.w3.org/1999/xhtml">なりません</strong></anchor> <src xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:10:"><anchor-internal xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:" a0:anchor="11" xmlns:a0="urn:x-suika-fam-cx:markup:suikawiki:0:9:">&gt;&gt;11</anchor-internal></src>。</p><p><anchor-end xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:" a0:anchor="4" xmlns:a0="urn:x-suika-fam-cx:markup:suikawiki:0:9:">[4]</anchor-end> 実装時は、<anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">バッファー</anchor>に一時的に<anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">フレーム</anchor>を書き込み、
適当な時機に <anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">OS</anchor> (<anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">ソケット層</anchor>) に引き渡すこととなります。
素朴な実装は、<anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">WebSocketメッセージ送信</anchor>時に即座に<anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">ソケット</anchor>に送信する
(= <anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">バッファリング</anchor>しない) こととなります。より高度な実装は、その時機を調整できます。</p><p><anchor-end xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:" a0:anchor="5" xmlns:a0="urn:x-suika-fam-cx:markup:suikawiki:0:9:">[5]</anchor-end> <anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">アプリケーション</anchor>内での<anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">バッファリング</anchor>は、
<code class="DOMa" xml:lang="en"><anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">bufferedAmount</anchor></code> <anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">属性</anchor>によって<anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">著者</anchor>が観測できます。
この<anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">属性</anchor>の値は、 <anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">event loop step 1</anchor> で更新されます。</p><p><anchor-end xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:" a0:anchor="7" xmlns:a0="urn:x-suika-fam-cx:markup:suikawiki:0:9:">[7]</anchor-end> <anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">アプリケーション</anchor>の<anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">バッファー</anchor>から<anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">ネットワーク</anchor>側へと引き渡されるまで、
<code class="DOMi" xml:lang="en"><anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">WebSocket</anchor></code> <anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">オブジェクト</anchor>は<anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">ごみ収集</anchor>されないことになっています。</p><comment-p xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:10:"><anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:"><code xmlns="http://www.w3.org/1999/xhtml" class="DOMi" xml:lang="en">WebSocket</code>のごみ収集</anchor>を参照。</comment-p><p><anchor-end xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:" a0:anchor="6" xmlns:a0="urn:x-suika-fam-cx:markup:suikawiki:0:9:">[6]</anchor-end> <anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">TCP</anchor> の<anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">フロー制御</anchor>などを含む <anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">OS</anchor> 側での<anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">バッファリング</anchor>は、
<anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">アプリケーション</anchor>からは検知できません。</p><p><anchor-end xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:" a0:anchor="10" xmlns:a0="urn:x-suika-fam-cx:markup:suikawiki:0:9:">[10]</anchor-end> <anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">Chrome</anchor> はすべて1つの<anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">フレーム</anchor>で送信するようです。 (しかし<anchor xmlns="urn:x-suika-fam-cx:markup:suikawiki:0:9:">GB</anchor>級のデータを送ろうとすると、クラッシュします。) <time>2015-08-22T06:21:33.600Z</time></p></section></body></html>