/
322.txt
368 lines (296 loc) · 21.6 KB
/
322.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
* 仕様書
[REFS[
- [1] [CITE@en[RFC 6455 - The WebSocket Protocol]] ([TIME[2015-03-11 20:42:50 +09:00]] 版) <http://tools.ietf.org/html/rfc6455#section-5.5.1>
- [12] [CITE@en[RFC 6455 - The WebSocket Protocol]] ([TIME[2015-03-11 20:42:50 +09:00]] 版) <http://tools.ietf.org/html/rfc6455#section-7>
- [49] [CITE@en[RFC 6455 - The WebSocket Protocol]] ([TIME[2015-03-11 20:42:50 +09:00]] 版) <http://tools.ietf.org/html/rfc6455#section-8>
- [52] [CITE@en[RFC 6455 - The WebSocket Protocol]] ([TIME[2015-03-11 20:42:50 +09:00]] 版) <http://tools.ietf.org/html/rfc6455#section-11.7>
- [54] [CITE[RFC Errata Report]] ([TIME[2015-05-16 22:26:12 +09:00]] 版) <http://www.rfc-editor.org/errata_search.php?rfc=6455>
- [55] [CITE[WebSocket Protocol Registries]] ([TIME[2015-03-06 13:09:47 +09:00]] 版) <https://www.iana.org/assignments/websocket/websocket.xml#close-code-number>
- [57] [CITE[Re: '''['''hybi''']''' Additional WebSocket Close Error Codes]] ([TIME[2012-05-26 08:20:06 +09:00]] 版) <http://www.ietf.org/mail-archive/web/hybi/current/msg09670.html>
- [58] [CITE@en-GB-x-hixie[HTML Standard]] ([TIME[2015-05-06 10:42:35 +09:00]] 版) <https://html.spec.whatwg.org/#dom-websocket-close>
- [62] [CITE@en-GB-x-hixie[HTML Standard]] ([TIME[2015-05-06 10:42:35 +09:00]] 版) <https://html.spec.whatwg.org/#feedback-from-the-protocol>
- [77] [CITE@en-GB-x-hixie[HTML Standard]] ([TIME[2015-05-06 10:42:35 +09:00]] 版) <https://html.spec.whatwg.org/#closeevent>
]REFS]
* [CODE(DOMi)@en[WebSocket]] インターフェイス [CODE(DOMm)@en[close]] メソッド
[59] [CODE(DOMi)@en[[[WebSocket]]]] [[インターフェイス]]の
[DFN[[CODE(DOMm)@en[[[close]]]]]] [[メソッド]]は、
次のようにしなければ[['''なりません''']] [SRC[>>58]]。
[FIG(steps)[
= 第1引数があれば、 [CODE(IDL)@en[[[unsigned short]]]] として解釈します。
[CODE(IDL)@en[[[Clamp]]]] [[拡張属性]]を適用します。
= 第2引数があれば、 [CODE(IDL)@en[[[USVString]]]] として解釈します。
= 第1引数が [CODE[[[1000]]]] か [CODE[[[3000]]]]-[CODE[[[4999]]]] の範囲になければ、
[CODE(DOMe)@en[[[InvalidAccessError]]]] [[例外]]を投げ、停止します。
= 第2引数があれば、
== [[UTF-8]] で[[符号化]]します。
== 124バイト[[以上]]なら、 [CODE(DOMe)@en[[[SyntaxError]]]] [[例外]]を投げ、停止します。
= [CODE(DOMa)@en[[[readyState]]]] が [CODE(DOMc)@en[[[CLOSING]]]] ([CODE[[[2]]]]) か
[CODE(DOMc)@en[[[CLOSED]]]] ([CODE[[[3]]]]) なら、何もしません。
= それ以外で、まだ[[WebSocket接続確立]]に達していなければ (= 接続の状態が
[CODE(DOMc)@en[[[CONNECTING]]]] なら)、
== [[WebSocket接続失敗]]を実行します。
== [CODE(DOMa)@en[[[readyState]]]] を、 [CODE(DOMc)@en[[[CLOSING]]]] ([CODE[[[2]]]]) に設定します。
= それ以外で、まだ [[The WebSocket Closing Handshake is Started]] に達していなければ
(= 接続の状態が [CODE(DOMc)@en[[[OPEN]]]] なら)、
== [[Start the WebSocket closing handshake]] を実行します。
第1引数があれば[[状態符号]]、第2引数があれば理由として引き渡します。
== [CODE(DOMa)@en[[[readyState]]]] を、 [CODE(DOMc)@en[[[CLOSING]]]] ([CODE[[[2]]]]) に設定します。
= それ以外なら、
== [CODE(DOMa)@en[[[readyState]]]] を、 [CODE(DOMc)@en[[[CLOSING]]]] ([CODE[[[2]]]]) に設定します。
]FIG]
;; [60] 接続の状態と [CODE(DOMa)@en[[[readyState]]]] は異なることがあります。
[[WebSocket接続]]を参照。
* [CODE[Close]] フレーム
** 構文
[2] [[opcode]] は、 [CODE[0x8]] です [SRC[>>1]]。
[CODE[[[Close]]]] [[フレーム]]は、[[制御フレーム]]です。
[3] 閉じる理由を示す[RUBYB[[[本体]]]@en[body]] ([[応用データ]]) を含んで構いません [SRC[>>1]]。
[4] 本体がある場合、最初の2バイトは[[ネットワークバイト順]]の2バイト[[符号無し整数]]でなければ[['''なりません''']]。
この[[整数]]は、[[状態符号]]でなければ[['''なりません''']]。 [SRC[>>1]]
[5] 本体は更に [[UTF-8]] 符号化されたデータを含めることができます。
その解釈は [[WebSocket]] 仕様書では規定されておらず、[[人間可読]]である必要もありませんが、
[[デバッグ]]などに有用かもしれません。[[クライアント]]はこれを[[末端利用者]]に示しては[['''なりません''']]。
[SRC[>>1]]
;; [22] この部分は「[DFN[[[close reason]]]]」[SRC[>>12]] と呼ばれています。
** 文脈
[10] 次の各項を参照。
[FIG(list)[
- [[WebSocketフレーム]]
]FIG]
;; [11] [[WebSocket接続の確立]]の途中での切断では、 [CODE[[[Close]]]]
[[フレーム]]は使いません。
** 処理
[6] [[応用]]は、 [CODE[[[Close]]]] [[フレーム]]より後に[[データフレーム]]を送っては[['''なりません''']]
[SRC[>>1]]。
[7] [[応用]]は、 [CODE[[[Close]]]] [[フレーム]]を受信した場合で、自身が前に送っていない場合は、
[CODE[[[Close]]]] [[フレーム]]を返送しなければ[['''なりません''']] [SRC[>>1]]。
これはできるだけすぐに行う[['''べきです''']]が、
現在のメッセージをすべて送り終えるまで遅延させても構いません [SRC[>>1]]。
返送する場合は、受信した[[状態符号]]をそのまま返すのが普通です [SRC[>>1]]。
ただし[[WebSocket接続失敗]]後は送信しては[['''なりません''']] [SRC[>>12]]。
;; [8] もっとも、 [CODE[[[Close]]]] が送られたということは、
その相手がそれ以後受信したデータを処理する保証はありません [SRC[>>1]]。
[9] [CODE[[[Close]]]] の送受信の後、[[WebSocket接続]]は閉じられたものとし、
[[TCP接続]]も閉じなければ[['''なりません''']]。[[サーバー]]は、
直ちに閉じなければ[['''なりません''']]。[[クライアント]]は、
[[サーバー]]が閉じるのを待つ[['''べき''']]ですが、いつでも (適当な[[タイムアウト]]時間後などに)
閉じて構いません。 [SRC[>>1]]
[50] 理由が [[UTF-8]] として[[妥当]]でなければ、[[WebSocket接続失敗]]しなければ[['''なりません''']] [SRC[>>49]]。
;; [51] が、無視して閉じる処理を続ける方が適切かもしれません。
* 状態符号と理由
[41] [[[CODE[Close]]フレーム]]には、閉じる理由を記述できます。
数値の[[状態符号]]と、任意の文字列を記述できます。
受信者による理由の解釈や処理方法は、 [[WebSocket Protocol]]
としては規定されていません [SRC[>>12]]。
[53] [[状態符号]]には、[[IANA登録簿]]があります [SRC[>>52, >>55]]。
[42] 次の[DFN[[RUBYB[[[状態符号]]]@en[status code]]]]が定義されています。
[FIG(list)[
- [DFN[[CODE(HTTP)[[[1000]]]]]] は、目的を達し正常に閉じられることを表します [SRC[>>12]]。
- [DFN[[CODE(HTTP)[[[1001]]]]]] は、[[サーバー]]のダウンや[[Webブラウザー]]が他ページに
[[navigate]] したなど通信の当事者が“いなく”なったことを表します [SRC[>>12]]。
- [DFN[[CODE(HTTP)[[[1002]]]]]] は、プロトコルエラーにより[[接続]]を閉じることを表します
[SRC[>>12]]。
- [DFN[[CODE(HTTP)[[[1003]]]]]] は、受け付けられないデータの種類のため[[接続]]を閉じる
(例えば[[テキスト]]しか理解できないのに[[バイナリー]]を受信した) ことを表します [SRC[>>12]]。
- [DFN[[CODE(HTTP)[[[1007]]]]]] は、データが種類に合っていない
(例えば[[テキスト]]のはずなのに [[UTF-8]] データでない) ため[[接続]]を閉じることを表します
[SRC[>>12]]。
- [DFN[[CODE(HTTP)[[[1008]]]]]] は、方針に反するメッセージを受信したため[[接続]]を閉じることを表します。
他により適切な[[状態符号]]がない時や、隠す必要がある時に使うことができます。 [SRC[>>12]]
- [DFN[[CODE(HTTP)[[[1009]]]]]] は、メッセージが大きすぎるため[[接続]]を閉じることを表します
[SRC[>>12]]。
- [DFN[[CODE(HTTP)[[[1010]]]]]] は、[[handshake]] 時に[[サーバー]]が期待していた[[拡張]]を返さなかったために[[クライアント]]が[[接続]]を閉じることを表します。
必要な[[拡張]]を [[[CODE[Close]]フレーム]]の理由部分に記述する[['''べきです''']]。 [SRC[>>12]]
- [DFN[[CODE(HTTP)[[[1011]]]]]] は、予期せぬ状況で要求を満足できず、[[接続]]を閉じることを表します [SRC[>>12, >>54]]。
- [DFN[[CODE(HTTP)[[[1012]]]]]] は、サービスが再起動されたことを表します。
[[クライアント]]は再接続して構いません。その場合 5s-30s から[[無作為]]に選んだ分遅延して再接続するべきです。 [SRC[>>57]]
- [DFN[[CODE(HTTP)[[[1013]]]]]] は、サービスが過負荷であることを表します。
[[クライアント]]は、(あれば) 異なる [[IPアドレス]]に接続するか、
[[利用者]]の指示があれば同じ [[IPアドレス]]に再接続することとするべきです。 [SRC[>>57]]
]FIG]
[43] [CODE(HTTP)[[[1004]]]] は、予約されています [SRC[>>12]]。
[44] [CODE(HTTP)[[[1015]]]] は、[[TLS handshake]] に失敗して[[接続]]が閉じられたことを示します。
[[[CODE[Close]]フレーム]]で使っては[['''なりません''']]。 [SRC[>>12]]
また[[利用者エージェント]]は使用しません [SRC[>>62]]。
;; [76] [CODE(HTTP)[[[1015]]]] が使われる場面はありません。理論上は[[サーバー]]が接続失敗時に[[ログ]]などで使うのかもしれませんが。。。
[45] [CODE[[[0]]]]-[CODE[[[999]]]] は、使いません [SRC[>>12]]。
[46] [CODE[[[1000]]]]-[CODE[[[2999]]]] は、公開された仕様書で規定されるプロトコルや拡張により、
永続的なものとして利用します [SRC[>>12]]。
[47] [CODE[[[3000]]]]-[CODE[[[3999]]]] は、
[[ライブラリー]]、[[フレームワーク]]、[[応用]]で使うために予約されています。
[[IANA登録簿]]に登録できます。 [SRC[>>12]]
[48] [CODE[[[4000]]]]-[CODE[[[4999]]]] は、
[[私用]]に予約されています。[[IANA登録簿]]に登録できません。
[[応用]]間の事前の合意で使うことができます。 [SRC[>>12]]
;; [56] 実際には「予約」として登録されています [SRC[>>55]]。
[65] 使ってはならない[[状態符号]]や予約されている[[状態符号]]は、
使ってはならないだけで、使われない保証は無いようです。
[30] [DFN[[RUBYB[WebSocket接続閉じ符号]@en[The WebSocket Connection Close Code]]]]は、
[[応用]]が最初に受信した [[[CODE[Close]]フレーム]]に含まれていた[[状態符号]]です。
当該[[フレーム]]が[[状態符号]]を含まない時は、 [DFN[[CODE[[[1005]]]]]] です。
そのような[[フレーム]]が無いまま [[The WebSocket Connection is Closed]]
となった場合は、 [DFN[[CODE[[[1006]]]]]] です。
[CODE(HTTP)[[[1005]]]] と [CODE(HTTP)[[[1006]]]] は、
[[[CODE[Close]]フレーム]]で使っては[['''なりません''']]。 [SRC[>>12]]
[31] [[サーバー]]と[[クライアント]]はそれぞれ[[状態符号]]を送ったり送らなかったりしますが、
両者の認識する[[WebSocket接続閉じ符号]]は同じかもしれませんし、違うかもしれません。
[32] [DFN[[RUBYB[WebSocket接続閉じ理由]@en[The WebSocket Connection Close Reason]]]]は、
[[応用]]が最初に受信した [[[CODE[Close]]フレーム]]に含まれていた閉じる理由
([[UTF-8]] として[[復号]]した[[文字列]]) です。そのようなものが無ければ、
[[空文字列]]です。 [SRC[>>12]]
* 閉じ handshake
[20] [DFN[[[Start the WebSocket Closing Handshake]]]] とは、
次のようにしなければ[['''なりません''']] [SRC[>>12]]。
[FIG(steps)[
= [21] [[フレーム]]を送信します。
[FIG(list members)[
[FIGCAPTION[
[[フレーム]]
]FIGCAPTION]
:[CODE[[[opcode]]]]:[CODE[[[Close]]]]
:[[状態符号]]:指定された値
:[[close reason]]:あれば、指定された値
]FIG]
= [24] [[WebSocket接続]]の状態を [CODE[[[CLOSING]]]] とします。
= [23] [[[CODE[Close]]フレーム]]を受信し(てい)たら、
[[WebSocket接続を閉じる]][['''べき''']]です。
]FIG]
[25] [[[CODE[Close]]フレーム]]を受信したら、
[[WebSocket接続]]の状態を [CODE[[[CLOSING]]]] とします [SRC[>>12]]。
[26] [[WebSocket接続]]の状態が [CODE[[[CLOSING]]]] となる時、
[DFN[[[The WebSocket Closing Handshake is Started]]]] といいます [SRC[>>12]]。
[61] [[the WebSocket closing handshake is started]] の際、
次の[[タスク]]を[[タスクキュー]]に追加しなければ[['''なりません''']] [SRC[>>62]]。
[FIG(list members)[
[FIGCAPTION[
[[タスク]]
]FIGCAPTION]
:[[タスク源]]:[[WebSocketタスク源]]
:処理:
[FIG(steps)[
= [CODE(DOMa)@en[[[readyState]]]] を、 [DFN[[CODE(DOM)@en[[[CLOSING]]]]]] ([CODE[[[2]]]])
に設定します。
]FIG]
]FIG]
;; [63] 既に [CODE(DOM)@en[[[CLOSING]]]] になっている場合もあります。
[36] [[クライアント]]は、[[応用]]から指示された場合や[[プロトコル]]で規定されている場合を除き、
[[接続]]を閉じる[['''べきではありません''']] [SRC[>>12]]。
閉じる場合は、 [[Start the WebSocket Closing Handshake]] を実行します [SRC[>>12]]。
[40] [[サーバー]]は、適宜接続を閉じて構いません [SRC[>>12]]。
閉じる場合は、 [[Start the WebSocket Closing Handshake]] を実行します [SRC[>>12]]。
* 接続失敗
[7] [[WebSocket接続の確立]]や[[WebSocketフレーム]]の解釈により、
[DFN[[RUBYB[WebSocket接続失敗]@en[Fail the WebSocket Connection]]]]となることがあります。
[33] [[クライアント]]は、次のようにしなければ[['''なりません''']] [SRC[>>12]]。
[FIG(steps)[
= [[WebSocket接続確立]]しているなら、適切な[[状態符号]]の
[[[CODE[Close]]フレーム]]を送信する[['''べきです''']]。
エラーの性質上相手が受信して処理しないだろうと思われるなら、省略して構いません。
= [[WebSocket接続を閉じる]]処理を実行します。
= [[利用者]]に問題を報告しても構いません。
]FIG]
[34] [[サーバー]]は、次のようにしなければ[['''なりません''']] [SRC[>>12]]。
[FIG(steps)[
= [[WebSocket接続確立]]しているなら、適切な[[状態符号]]の
[[[CODE[Close]]フレーム]]を送信する[['''べきです''']]。
エラーの性質上相手が受信して処理しないだろうと思われるなら、省略して構いません。
= [[WebSocket接続を閉じる]]処理を実行します。
= 問題を記録する[['''べきです''']]。
]FIG]
[35] [[WebSocket接続失敗]]以後、受信したデータを処理し続けようとしては[['''なりません''']]。
これには、 [[[CODE[Close]]フレーム]]への返信も含まれます。 [SRC[>>12]]
* 接続を閉じる
[13] [DFN[[RUBYB[WebSocket接続を閉じる]@en[Close the WebSocket Connection]]]]時には、
下位[[TCP接続]]を閉じます [SRC[>>12]]。[[サーバー]]は、直ちに [[TCP]]
を閉じる[['''べきです''']] [SRC[>>12]]。[[クライアント]]は、
[[サーバー]]から [[TCP]] が閉じられるのを待つ[['''べきです''']] [SRC[>>12]]。
[14] [[TCP接続]]と[[TLSセッション]]を綺麗に閉じる方法を使い、
受信したかもしれない[[バイト]]は捨てる[['''べきです''']] [SRC[>>12]]。
[16] 最も通常な場合には、まず ([[クライアント]]からではなく)
[[サーバー]]から [[TCP接続]]を閉じる[['''べきです''']] [SRC[>>12]]。
;; [17] そうすることで、[[クライアント]]ではなく[[サーバー]]の [[TCP]]
が [CODE[[[TIME_WAIT]]]] 状態となります。 [CODE[[[TIME_WAIT]]]] 状態である
[[最大セグメント寿命]]の2倍 (2[[MSL]]) の間は改めて[[接続]]を開くことができませんが、
[[サーバー]]側ならより大きな[[シーケンス番号]]の [CODE[[[SYN]]]] を送信すれば直ちに[[接続]]を開けるので問題となりません。 [SRC[>>12]]
[EG[
[19] 例えば [[socket]] API では、
まず [CODE[[[SHUT_WR]]]] を指定して [CODE[[[shutdown]]]] を呼び出し、
[CODE[[[0]]]] が返されるまで [CODE[[[recv]]]] を呼び出し、
最後に [CODE[[[close]]]] を呼ぶことでこれを実装できます [SRC[>>12]]。
]EG]
[15] 攻撃されている時など、必要に応じて他の方法で閉じても構いません [SRC[>>12]]。
[18] 十分な時間[[サーバー]]から [[TCP]] Close を受信しない場合などには[[クライアント]]から
[[TCP]] を閉じて構いません [SRC[>>12]]。
[27] [[TCP接続]]が閉じられた時、
[DFN[[[The WebSocket Connection is Closed]]]] といいます [SRC[>>12]]。
この時、 [[WebSocket接続]]の状態は [DFN[[CODE[[[CLOSED]]]]]]
([CODE[[[3]]]]) となります [SRC[>>12]]。
;; [29] [[WebSocket接続]]が確立できなかった時も、
[[The WebSocket Connection is Closed]] といいます。 [[cleanly]] ではありません。 [SRC[>>12]]
[28] [[WebSocket接続]]の閉じ handshake が完了してから [[TCP接続]]が閉じられたなら、
「[DFN[[[cleanly]]]]」に閉じられたといいます [SRC[>>12]]。
そうでなければ [[cleanly]] ではありません。
[64] [[the WebSocket connection is closed]] なら、次の[[タスク]]を[[タスクキュー]]に追加しなければ[['''なりません''']] [SRC[>>62]]。
[FIG(list members)[
[FIGCAPTION[
[[タスク]]
]FIGCAPTION]
:[[タスク源]]:[[WebSocketタスク源]]
:処理:
[FIG(steps)[
= [CODE(DOMa)@en[[[readyState]]]] を、 [CODE(DOM)@en[[[CLOSED]]]] ([CODE[[[3]]]])
に設定します。
= [[WebSocket接続失敗]]の場合や、 [[flagged as full]] が設定されてから
[[the WebSocket connection is closed]] となったなら、
[[単純イベントを発火]]します。
[FIG(list members short)[
[FIGCAPTION[
[[単純イベント]]
]FIGCAPTION]
:[[イベント型]]:[CODE(DOMe)@en[[[error]]]]
:[[対象オブジェクト]]:[CODE(DOMi)@en[[[WebSocket]]]] [[オブジェクト]]
]FIG]
= [[イベント]]を[[発火]]します。
[FIG(list members short)[
[FIGCAPTION[
[[イベント]]
]FIGCAPTION]
:[[インターフェイス]]:[CODE(DOMi)@en[[[CloseEvent]]]]
:[[イベント型]]:[CODE(DOMe)@en[[[close]]]]
:[[対象オブジェクト]]:[CODE(DOMi)@en[[[WebSocket]]]] [[オブジェクト]]
:[[bubbles]]:[[偽]]
:[[取り消し可能]]:[[偽]]
:[[既定動作]]:なし
:[CODE(DOMa)@en[[[wasClean]]]]:[VAR[cleanly]]
:[CODE(DOMa)@en[[[code]]]]:[[WebSocket接続閉じ符号]]
:[CODE(DOMa)@en[[[reason]]]]:[[WebSocket接続閉じ理由]]
]FIG]
]FIG]
]FIG]
[78] [CODE(DOMi)@en[[[CloseEvent]]]] [[インターフェイス]]の
[DFN[[CODE(DOMa)@en[[[wasClean]]]]]] [[属性]]は、 [VAR[cleanly]]
に閉じられたかどうかを表します。
[79] この[[属性]]は、その[[属性値]]として設定された値を返さなければ[['''なりません''']] [SRC[>>77]]。[[データ型]]は [CODE(IDL)@en[[[boolean]]]] で、初期値は[[偽]]です [SRC[>>77]]。
[66] [[利用者エージェント]]は、[[スクリプト]]に次の状況を区別できる情報を提供しては[['''なりません''']] [SRC[>>62]]。
[FIG(list)[
- [67] [[ホスト名]]が[[名前解決]]できなかった場合
- [68] [[サーバー]]に[[パケット]]を配送する[[経路]]を見つけられなかった場合
- [69] [[ポート]]への[[接続]]が拒まれた場合
- [70] [[TLS handshake]] に失敗した場合 (例えば[[証明書]]を検証できなかった場合)
- [71] [[WebSocket handshake]] を完了できなかった場合
- [72] [[WebSocket handshake]] は完了したものの、[[クライアント]]が[[接続]]を閉じる状況となった場合 (例えば[[クライアント]]が想定しない[[部分プロトコル]]を[[サーバー]]が指定した場合)
- [73] [[WebSocket handshake]] は成功したものの[[接続]]が予期せず閉じられた場合
]FIG]
[74] このような場合の[[WebSocket接続閉じ符号]]はいずれも [CODE[[[1006]]]] となります [SRC[>>62]]。
;; [75] こうした状況を区別できるとすると、[[スクリプト]]が[[利用者]]の属するネットワークの状態を調べるために使えてしまいます [SRC[>>62]]。
* 異常終了
[37] [[クライアント]]は、[[トランスポート層]]の[[接続]]が失われたら、
[[WebSocket接続失敗]]を実行しなければ[['''なりません''']] [SRC[>>12]]。
[39] [[クライアント]]が[[WebSocket接続失敗]]の後再接続を試みる際は、
何らかの [[backoff]] を行う[['''べきです''']]。
最初の再接続は、[[無作為]]に決めた時間だけ遅延させる[['''べきです''']]。
0s-5s の間から[[無作為]]に決めるのが妥当でしょうが、
実装経験や[[応用]]に基づき任意の方法で決めて構いません。
それ以後の再接続は、[RUBYB[[[冪乗打ち切り待機法]]]@en[truncated binary exponential backoff]]などにより徐々に時間を長くしていく[['''べきです''']]。 [SRC[>>12]]
[38] [[サーバー]]が [DFN[[[Abort the WebSocket Connection]]]] するとは、
[[WebSocket接続を閉じる]]処理を実行しなければ[['''なりません''']] [SRC[>>12]]。