NodeJSサーバ + C#WebSocketクライアントを試す

websocket-sharpで検索するとUnityでの利用例が多く出てくる。
最終的にUnityで使う可能性はあるが、普通にC#クライアントとしてWebSocketを使う手段を確認しておく。

# websocket-sharpのビルド
クライアント側は少し古いもののwebsocket-sharpを使って繋ぐのが良さそう。ライセンスはMITなので問題なし。
gitからダウンロードしてビルドする、という手段がまずは必要らしい。

Unityだとアセット云々という記載もgitには記載があるが、[gitからダウンロード](https://github.com/sta/websocket-sharp)する。
gitからcloneする手もあるが、右上のCodeからzipダウンロードでコードをダウンロードして展開。
Example系のフォルダを削除。

VSCodeでフォルダを読み込んで、Ctrl+Shift+Bでテンプレートからビルドタスクを選択、タスクファイルを作って・・・という事も出来るようだが面倒なので
`msbuild.exe /p:Configuration=Release websocket-sharp.sln`
で行う。
`MSBUILD : error MSB4132: ツール バージョン "3.5" が認識されません。使用可能なツール バージョンは "14.0", "4.0" です。`
が出たので、.NET3.5をインストールされているサーバにファイルをコピーして実行。
`C:\Windows\Microsoft.NET\Framework\v3.5\MSBuild.exe  /p:Configuration=Release websocket-sharp.sln`
Exampleを削除しているのでいくつかエラーは出るが、webxoket-sharp\bin\Releaseにdllが作成されている。

CookieException云々という記事もあるが、dllが出来ているので放置

#サーバ
node.js（16.x）を利用して立てる。
前回はsocket.ioで簡単にブラウザと連携する形で作成したが、今回はwsを使う。
Unityとの連携だと[ここ](https://qiita.com/nmxi/items/d3a0e787ca67e27ffd17)とかでやってる。

メッセージを受け取ったらコンソールに出して、レスポンスを返すだけのもの。

```javascript
const server = require("ws").Server;
const s = new server({ port: 5001 });

s.on("connection", ws => {
    ws.on("message", message => {
        console.log("Received: " + message);
        ws.send("server response");
    });
});
```

# クライアント
VSは入れていないため、C#のソースはcsc.exeでコンパイル。
`The type or namespace name 'WebSocketSharp' could not be found `になる。
`csc.ect /r:websocket-sharp.dll socket.cs`
のように/rオプションで外部dllを使ったソースのコンパイルが可能。

非同期にする必要もないのでThread.Sleepで1秒毎に通信。

```C#
using WebSocketSharp;
using System;
using System.Threading;

class socket {

    static void Main(string[] args) {
        WebSocket _webSocket;

        const string WEBSOCKET_URL = "ws://localhost:5001/";
        
        _webSocket = new WebSocket(WEBSOCKET_URL);

        _webSocket.OnMessage += (sender, e) => Console.WriteLine(e.Data);
        _webSocket.OnClose += (sender, e) => Console.WriteLine("Close");

        _webSocket.Connect();

        while(true){
            Delay1000(_webSocket);
        }
    }

    static void Delay1000(WebSocket skt)
    {  
        try{
            skt.Send("Send message");
        }
        catch(Exception ex){
            Console.WriteLine(ex);
        }
        Thread.Sleep(1000);
    }
}
```

割と簡単に出来た。

# ブラウザからの接続
この前とは違ってサーバがwsなので、普通にJavaScriptでの送受信も試しておく。

```html
<html>
    <body>
        <div>
            <input
                id="send-message"
                type="text"
                placeholder="メッセージを入力"
            >
        </div>
        <div>
            <button id="send-button" onClick="sendMessage(document.getElementById('send-message').value)">
            メッセージ送信
            </button>
        </div>
        <div id="res-message">
            <!-- 表示エリア -->
        </div>
    <script>
    // 接続設定
    const URL = 'ws://localhost:5001/';
    const SUBPROTOCOL = 'ws-sample';

    // WebSocket 通信を開始する
    // const socket = new WebSocket(URL, SUBPROTOCOL);
    const socket = new WebSocket(URL);

    // ------------------------------
    // WebSocket イベント
    // ------------------------------

    // WebSocketOpen時
    socket.addEventListener('open', (event) => {
        console.log('open');
        socket.send('OpenMessage'); // メッセージの送信
    });

    // WebSocket受け取り時
    socket.addEventListener('message', ({ data }) => {
        resMessage(data);
    });

    // WebSocketエラー時
    // socket.onerror = () => {} でも可
    socket.addEventListener('error', (event) => {
        console.log('error');
    });

    // WebSocket がクローズしたら発火する
    // socket.onclose = () => {} でも可
    socket.addEventListener('close', (event) => {
        console.log('close');
    });

    // メッセージ送信 
    const sendMessage = (message) => {
        socket.send(message)
    }

    // 受信メッセージ表示
    const resMessage = (message) => {
        var new_element = document.createElement('div');
        new_element.textContent = message;
        document.getElementById('res-message').appendChild(new_element);
    } 
    </script>
    </body>
</html>
```

# その他メモ
[これ](https://qiita.com/bagooon/items/d59b36eae1d938fb3549)とか[これ](https://codenote.net/javascript/4763.html)
で書いているように再接続を便利にしてくれるライブラリがある。