[C#]WebSocketを試してみる。お手軽シンプルブロードキャストエコーサーバー作成の巻。

ブロードキャストエコーサーバー
WebSocketのテスト用。
送信時にちょっと工夫。ユーザーに送信する際にParallel.ForEach()を使用して並列化してみた。これを使うと複数ユーザーに送信する処理を並列化できる。例えば大きいデータなどを分割して送りたい処理などに有効。但し、リソースの消費量が大きくなるので注意が必要。Parallel.ForEach()はマルチコアCPUをフル活用するからパソコンのファンがブーンって鳴る。

並列化の効用。
複数の画像を各クライアントにプッシュ配信するサーバーの例。合計1.77MBの画像データを8KBパケットに分割して送信するとします。実行画面では1フォルダにつき1クライアントが動作しています。

以下、シンプルブロードキャストサーバーのソース。
サーバーソース

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using SuperSocket.Common;
using SuperSocket.SocketBase;
using SuperSocket.SocketBase.Config;
using SuperSocket.SocketEngine;
using SuperWebSocket;

namespace WsEchoServer
{
    class Program
    {
        static void Main(string[] args)
        {
            /// WebSocket初期化
            var server = new SuperWebSocket.WebSocketServer();
            var rootConfig = new SuperSocket.SocketBase.Config.RootConfig();
            var serverConfig = new SuperSocket.SocketBase.Config.ServerConfig()
            {
                Port = 12345,
                Ip = "Any",
                MaxConnectionNumber = 100,       /// 最大ユーザセッション数
                Mode = SocketMode.Sync,
                Name = "Echo Server"
            };

            /// クライアントセッションを格納
            var clinet_sessions = new List<WebSocketSession>();

            /// セッションの接続
            server.NewSessionConnected += (s) =>
                {
                    Console.WriteLine("{0}:New Session:{1}", DateTime.Now.ToString(), s.RemoteEndPoint.Address.ToString());

                    /// 新クライアントとして格納
                    clinet_sessions.Add(s);
                };

            /// セッションのクローズ
            server.SessionClosed += (s, r) =>
                {
                    Console.WriteLine("{0}:Session Close:{1}", DateTime.Now.ToString(), s.RemoteEndPoint.Address.ToString());

                    /// 該当クライアントの除外
                    clinet_sessions.Remove(s);
                };

            /// データ受信(バイナリ)
            server.NewDataReceived += (s, d) =>
                {
                    Console.WriteLine("{0}:Binary Received:{1}", DateTime.Now.ToString(), s.RemoteEndPoint.Address.ToString());
                    Console.WriteLine("Length={0}", d.Length);
                    
                    /// 全ユーザに送信
                    Parallel.ForEach(clinet_sessions, p => p.SendResponse(d));
                };

            /// データ受信(文字列)
            server.NewMessageReceived += (s, m) =>
                {
                    Console.WriteLine("{0}:String Received:{1}",DateTime.Now.ToString(), s.RemoteEndPoint.Address.ToString());
                    Console.WriteLine("Message={0}", m);

                    /// 全ユーザに送信
                    Parallel.ForEach(clinet_sessions, p => p.SendResponse(m));
                };


            /// サーバセットアップ
            server.Setup(rootConfig, serverConfig, SocketServerFactory.Instance);
            /// サーバ起動
            server.Start();

            Console.WriteLine("{0}:Server start.",DateTime.Now.ToString());
        }
    }
}

クライアントにはWebSocket4Netを使用。
これまでクライアントにはWCF WebSocketsを使っていたけど、SuperWebSocketsに含まれていたWebSocket4Netを使用してみる。
ほぼWCF WebSocketsと使用感は変わらない。

WebSocket4Net
http://websocket4net.codeplex.com/

クライアントソース

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using WebSocket4Net;

namespace WsClient
{
    class Program
    {
        static void Main(string[] args)
        {
            var ws = new WebSocket("ws://192.168.1.2:12345");

            /// 文字列受信
            ws.MessageReceived += (s, e) =>
                {
                    Console.WriteLine("{0}:String Received:{1}", DateTime.Now.ToString(), e.Message);
                };

            /// バイナリ受信
            ws.DataReceived +=(s,e)=>
                {
                    Console.WriteLine("{0}:Binary Received Length:{1}", DateTime.Now.ToString(), e.Data.Length);
                };

            /// サーバ接続完了
            ws.Opened += (s, e) =>
            {
                Console.WriteLine("{0}:Server connected.", DateTime.Now.ToString());
            };

            /// サーバ接続開始
            ws.Open();

            /// 送受信ループ
            while (true)
            {
                var str = Console.ReadLine();
                if (str == "END") break;

                if (ws.State == WebSocketState.Open)
                {
                    ws.Send(str);
                }
                else
                {
                    Console.WriteLine("{0}:wait...", DateTime.Now.ToString());
                }
            }


            /// ソケットを閉じる
            ws.Close();

        }
    }
}

実行画面

今回作成したソースはこちら

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA


This blog is kept spam free by WP-SpamFree.