ブラウザからWSを通して送受信できるデータについて確認、実装を行います。
クライアントで扱うことができるデータタイプ
規格のレファランスから「Blob、ArrayBuffer」を扱っていることがわかりますが、MDNのレファランスからは「USVString」も追加でサポートしていることが記載されています。
「Blob」は基本的にファイルデータを指していますが、データを転送する際に「ArrayBuffer」からバイトを転送することと大きく変わりはないため、今回はByteデータの送信で検証します。
クライアントが受け取るデータタイプ
データ転送時とは違く、MDNのレファランスに記載されている内容が曖昧で実際に確認する必要がありそうです。
Value
The data sent by the message emitter; this can be any data type.
上記の記載だと、何を許容しているか明示されてないです。
MDNからだと、UTF-8の文字列以外は受け付けることができないと記載があります。
検証項目
今回は下記の項目を検証したいと考えてます。
- Byteデータ送信の検証
- Stringデータ送信の検証
- Byteデータ受信ができるか
- Stringデータ受信の検証
使用環境
Go >= 1.18
github.com/gorilla/websocket >= v1.5.0
Byteデータ送信の検証
クライアント側でByteデータを送信する機能の実装です。
バイト列の変数を送ることで、データの転送ができることを確認できます。
function ByteDataSend() {
const data = new Uint8Array(4)
data[0] = 0x01
data[1] = 0x02
data[2] = 0x03
data[3] = 0x04
socket.send(data)
}
クライアントログ
サーバーログ
Stringデータ送信の検証
クライアント側で文字列データを送信する機能の実装です。
文字列をそのまま送信することで、データの転送ができます。
function StringDataSend() {
socket.send("test Message")
}
クライアントログ
サーバーログ
Byteデータ受信ができるか
サーバー側で、受け取ったデータをそのまま返す、Echoサーバーのようにしました。
上記で作成したByteDataSend
メソッドを使います。
クライアント側でデータを転送したらサーバー側で受け取り、
返す際にサーバー側とクライアント側で想定外の動作をします。
- サーバー側の問題
扱うデータがUTF-8ではないとエラーが表示され、クライアントと接続が切断されます。
- クライアント側の問題
Byteデータは受け取ることはできますが、そのデータを取得することができません。
ここで確認した結果を見て、あくまで推論した結論ですがByteデータを扱うためには現状のWebSocketの実装だとWebRTCを使い、Byteデータをクライアント側で処理するようにするしかないと考えられます。
そもそも受け取らないことが原因でもありますが、その点以外にもWebSocketだと、データを一方的に送る、受け取ること自体もできるので仮にサーバーからバイナリデータを受信されて何かのファイルを書き込まれたりでクライアント側に何かしらの攻撃ができるのでセキュリティー観点からByteデータを受け取ることをできなくしているかと想定しています。
RFCからだと、そもそもできないようになっていることが原因になるかと思います。。
はっきりわかったのは、サーバーからクライアントへByteデータの送信はWebSocketだとできないことがわかりました。
Stringデータ受信の検証
Echoサーバーの構成で結果確認を行います。
上記で作成したStringDataSend
メソッドを使い確認を行います。
結果を見ると、問題なく文字列データがサーバー内で処理されて、クライアントで受信できていることがわかります。
クライアントログ
サーバーログ
終わりに
今回使ったソースコードは下記のURLにあります。ご確認いただければと思います。
文書だけはなかなか説明しづらい箇所もあるので参考にしたい際はご覧ください。