← 戻る

GameLiftのGo用Server SDKを作ってみたい(2)

2020-02-17

ということで、まず Engine.IO を調査してみた。 websocket だけの実装ではだめっぽいので、少なくとも polling/xhr は必要そう。

XHR クライアントに限定したら簡単に実装できそうかなあという印象。 upgrade 周り含めるとちょっと面倒そう。 あと、Ack は Engine.IO には含まれてないので Socket.IO まで見る必要がありそう。

次は、簡易でいいので Engine.IO の Go クライアントを用意してみる。

以下メモ。

[https://github.com/socketio/engine.io-protocol](https://github.com/socketio/engine.io-protocol) [https://github.com/socketio/engine.io-parser](https://github.com/socketio/engine.io-parser) [https://github.com/socketio/engine.io-client](https://github.com/socketio/engine.io-client)

Transport は Engine.IO の URL に対して接続を確立する サーバは open に対して sid, upgrades, pingTImeout, pingInterval を含む返信をする サーバは ping に対して pong しなければならない クライアントとサーバは message パケットを自由に交換する(おそらく Request-Response のように対になることなくそれぞれ勝手に、という意味) Polling している Transport はソケットを閉じるため close を送ることができる?`since they're expected to be "opening" and "closing" all the time.`がよくわからん

URL は`/engine.io/[?<query string>]` という形式。 query はオプショナルで、`transport`, `j`, `sid`, `b64`の 4 つが予約されている。 transport は Transport 名で、デフォルトでは`polling``websocket` j は transport が`polling`で JSONP response が要求されている時、JSONP response index が設定される sid はセッション ID。クライアントがセッション ID を与えられたら指定する必要あり b64 はクライアントが XHR2 をサポートしていない時 b64=1 となって、バイナリは base64 エンコードされて送られる

エンコーディング

packet と payload がある

packet は UTF8 文字列かバイナリデータ 文字列の場合、以下のフォーマット

```
[] ```

バイナリでも同じだけど、`packet type id`のところが最初の 1 バイトになる

パケットタイプは以下のものがある

0 open 新しい Transport が開いた時サーバからクライアントに送られる

1 close Transport を閉じる要求だが、自身のコネクションは閉じない? (Transport と Connection の違いがわからん?)

2 ping 3 pong Ping に来たデータをそのまま Pong する必要ある

4 message データをコールバックに渡して呼ぶ必要がある(プロトコルというよりライブラリの話)

5 upgrade Transport を切り替える前に新しい接続方法でいけるかテストする。テスト成功したらクライアントは upgrade を送って、新しい Transport に切り替わる。

6 noop poll cycle を強制するため incoming websocket connection を受け取った場合に使われる? (よくわからん)

payload

いくつかのパケットをつなげたもの

`<length1>:<packet1>[<length2>:<packet2>[...]]` つまり長さとパケットが交互に来る形 length は文字数で表現する packet は上で説明した通り

XHR2 がサポートされていない時は base64 エンコードされた文字列として送信する それを示すために b という文字がくっつく

```
:b ```

XHR2 がサポートされている時はこれ

```
<0 for string data, 1 for binary data>[...] ```

UTF8 文字列とバイナリデータの組み合わせが送信される時は、各文字の文字コードが 1 バイトずつ書き込まれる?

Payload は framing をサポートしていない transport で使われる。polling とか

Transport

websocket, polling がある polling には jsonp と xhr がある

polling は、クライアントからサーバに対する定期的な GET と、データ送信時の POST からなる

xhr では CORS レスポンスをサポートする必要がある jsonp ではサーバは正しい JavaScript を返信するよう実装する必要がある websocket ではフレーミングをサポートしているため payload は使ってはならない

connection は常に polling(xhr か jsonp)で開始する WebSocket は probe を送信するところでテストされ、probe が返れば upgrade される