🔌

WindowのC#でsocket.ioを利用する

2022/10/09に公開

はじめに

WindowアプリのC#でsocket.ioのクライアントを作成してみました。

https://socket.io/

前提条件

  • C#で作成するのはクライアント側
  • Socket.IO-client for .NETを利用する。(SocketIoClientDotNetではない)

https://github.com/doghappy/socket.io-client-csharp

  • サーバ側はNode.jsを利用する。
  • Node.jsのHTTPは3000で起動しているが、nginxでリバースプロキシしてhttps化している。
  • socket.ioのURLのパスは'/TEST1/socket.io'にしている。

A. サーバ側実装 for Node.js

index.js
var express = require('express');
var app = express();
var http = require('http').Server(app);
const io = require('socket.io')(http,{
    path: '/TEST1/socket.io',
}
);
const PORT = 3000;

io.on('connection',function(socket){
    socket.on('byClient_TEST1',function(msg){
        socket.emit("toClient_TEST2", {
            p1:"param1:" + msg,
            p2:2,
        });
    });

    socket.emit("toClient_TEST0", "complete to connect.");
});

app.get('/' , function(req, res){
   res.sendFile(__dirname + '/index.html');
});

http.listen(PORT, function(){
  console.log('Port:' + PORT);
});

その他のファイル

package.json
{
  "name": "test-server",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "nodemon index.js"
  },
  "keywords": [],
  "author": "",
  "license": "",
  "dependencies": {
    "express": "^4.18.1",
    "socket.io": "^4.5.2"
  }
}

実行手順

npm install -g nodemon
npm install
npm run dev

B. クライアント側実装 for C#

  • Formアプリで作成
  • Nugetで「Socket.IO-client for .NET」をインストール
  • button1とtextBox1,textBox2を配置
  • private SocketIO io_clientをローカル変数にすると、消失するのでインスタンス変数にする
Form1.cs
using SocketIOClient;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp2
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private SocketIO io_client;
        private string targetUrl = "https://.../"; // サーバ側のドメインを設定

        private SocketIOOptions createOptions()
        {
            return new SocketIOOptions
            {
                Path = "/TEST1/socket.io", // サーバ側のPath設定と必ず同じにする
            };
        }

        class Message1
        {
            [JsonPropertyName("p1")]
            public string p1 { get; set; }
            [JsonPropertyName("p2")]
            public int p2 { get; set; }
        }

        private async void button1_Click(object sender, EventArgs e)
        {
            io_client = new SocketIO(targetUrl, createOptions());
            io_client.On("toClient_TEST2", response =>
            {
                Message1 msg = response.GetValue<Message1>();
                this.Invoke((Action)(() =>
                {
                    this.textBox2.Text = msg.p1;
                }));
            });

            io_client.On("toClient_TEST0", response =>
            {
                string text = response.GetValue<string>();
                this.Invoke((Action)(() =>
                {
                    this.textBox1.Text = text;
                }));
            });

            io_client.OnConnected += async (sender2, e2) =>
            {
                await io_client.EmitAsync("byClient_TEST1", "TEST1 message.");
            };
            await io_client.ConnectAsync();
        }
    }
}

その他

非同期の双方向通信を行う場合socket.ioは便利なので利用することが多いです。
WebSocketでも良いのですがインフラの調整が必要になることがあるためサーバ側実装言語も増えてきています。
socket.ioはWebsocketが利用できない場合は、簡単に言えばサイズが不定で送信や応答をイベントタイミングまで行わないPOSTを繰り返す方法で実装されています。

Discussion