WebSocket Byte、Stringの送受信の検証

ブラウザからWSを通して送受信できるデータについて確認、実装を行います。


## クライアントで扱うことができるデータタイプ

[規格](https://websockets.spec.whatwg.org/#ref-for-dom-websocket-send%E2%91%A0)のレファランスから「Blob、ArrayBuffer」を扱っていることがわかりますが、[MDNのレファランス](https://developer.mozilla.org/ja/docs/Web/API/WebSocket/send)からは「USVString」も追加でサポートしていることが記載されています。
「Blob」は基本的にファイルデータを指していますが、データを転送する際に「ArrayBuffer」からバイトを転送することと大きく変わりはないため、今回はByteデータの送信で検証します。

## クライアントが受け取るデータタイプ

データ転送時とは違く、[MDNのレファランス](https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent/data)に記載されている内容が曖昧で実際に確認する必要がありそうです。

> Value
The data sent by the message emitter; this can be any data type.


<sup>*上記の記載だと、何を許容しているか明示されてないです。*</sup>

[MDN](https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent)からだと、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)

    }

### クライアントログ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1089747/f236420b-7976-cb51-c2ec-9261ece542a2.png)

### サーバーログ

![スクリーンショット 2022-06-23 22.00.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1089747/60be9830-2361-4768-ed2e-9b6a2cb5239d.png)
 
## Stringデータ送信の検証

クライアント側で文字列データを送信する機能の実装です。
文字列をそのまま送信することで、データの転送ができます。


    function StringDataSend() {

      socket.send("test Message")

    }


### クライアントログ

![スクリーンショット 2022-06-23 22.01.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1089747/6dc7543a-e931-432b-ca55-2a1fac7dc457.png)

### サーバーログ

![スクリーンショット 2022-06-23 22.02.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1089747/72066cdb-ad1e-516d-f77d-feea374e0714.png)

## Byteデータ受信ができるか

サーバー側で、受け取ったデータをそのまま返す、Echoサーバーのようにしました。
上記で作成した`ByteDataSend`メソッドを使います。
クライアント側でデータを転送したらサーバー側で受け取り、
返す際にサーバー側とクライアント側で想定外の動作をします。

- サーバー側の問題
　　　　扱うデータがUTF-8ではないとエラーが表示され、クライアントと接続が切断されます。
  ![スクリーンショット 2022-06-23 22.04.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1089747/f9b76d93-54eb-98f5-15a7-9b659543dfd4.png)
- クライアント側の問題
　　　　Byteデータは受け取ることはできますが、そのデータを取得することができません。
  ![スクリーンショット 2022-06-23 22.05.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1089747/ba2742a5-f754-931b-6d70-04b287e30ea8.png)

ここで確認した結果を見て、あくまで推論した結論ですがByteデータを扱うためには現状のWebSocketの実装だとWebRTCを使い、Byteデータをクライアント側で処理するようにするしかないと考えられます。
そもそも受け取らないことが原因でもありますが、その点以外にもWebSocketだと、データを一方的に送る、受け取ること自体もできるので仮にサーバーからバイナリデータを受信されて何かのファイルを書き込まれたりでクライアント側に何かしらの攻撃ができるのでセキュリティー観点からByteデータを受け取ることをできなくしているかと想定しています。
<sub>[RFC](https://datatracker.ietf.org/doc/html/rfc6455#section-8.1)からだと、そもそもできないようになっていることが原因になるかと思います。。</sub>

はっきりわかったのは、サーバーからクライアントへByteデータの送信はWebSocketだとできないことがわかりました。

## Stringデータ受信の検証

Echoサーバーの構成で結果確認を行います。
上記で作成した`StringDataSend`メソッドを使い確認を行います。
結果を見ると、問題なく文字列データがサーバー内で処理されて、クライアントで受信できていることがわかります。

### クライアントログ
![スクリーンショット 2022-06-23 22.06.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1089747/8f1bbd77-0fa7-6f54-a2f3-f56d095105a1.png)

### サーバーログ
![スクリーンショット 2022-06-23 22.06.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1089747/76a3ab1b-ab2d-dd43-ea0c-a6dfeafa3ff7.png)

## 終わりに

今回使ったソースコードは下記のURLにあります。ご確認いただければと思います。
文書だけはなかなか説明しづらい箇所もあるので参考にしたい際はご覧ください。

https://github.com/dlstjq7685/ws-DataTransfer