ブロードキャストエコーサーバー
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(); } } }
実行画面
今回作成したソースはこちら。