WebSocket(RFC 6455)上で使用するプロトコル設計についての備忘録
一般論として、全二重の通信プロトコルを実装するにあたっては、いくつか注意すべき点があって、具体的には、到達確認と切断シーケンスについて定めておかないと、送達されたはずのメッセージがロストしていたり、切断タイミングによってエラーが発生*1したりする。
具体例をあげると、たとえばTCP/IPにおいてshutdown(2)を用いずに、いきなりclose(2)を呼んでいると、read(2)やwrite(2)がエラー(ECONNRESET)を返す場合がある。
翻って、WebSocket (RFC6455)の場合はどうなってるか? だいたい以下のような感じっぽい。
- ws.close()が呼び出されるとWebSocketをCLOSING状態に変更し、Closeフレームを送信する
- ws.onmessageはWebCosketがCLOSING状態にある間も呼ばれるかもしれない*2
- 相手からCloseフレームを受け取った場合、自身がまだCloseフレームを送信していなければ可及的速やかにこれを送信し、自らの状態をCLOSEDに変更し、ws.oncloseを呼び出す
- 相手からCloseフレームを受け取った場合、自身が既にCloseフレームを送信していれば、自らの状態をCLOSEDに変更し、ws.oncloseを呼び出す
- TCP/IPソケットは両者がCloseフレームを送信した後に閉じられる
- WebSocket実装は、Closeフレームの送信後にデータを送信してはならない
以上より、WebSocket上で全二重の通信を行う場合、
ということがわかる。
参考: