[C#]System.Net.WebSocketsを試す。その1。ClientWebSocket編。

.NET Framework 4.5からサポートされているWebSocketのクライアント版。
これまでHTML5LabsのWCF WebSocketsを使用してきましたが、こちらは開発がストップ(?)しているようで、WebSocketsのプロトコルバージョンも古かったりします。もし、Windows7でWebSocketsを使用したデスクトップアプリケーションを作成する場合はSuperWebSocketsWebSocket4Netを導入するほうがよいでしょう。

本題のSystem.Net.WebSockets.ClientWebSocketですが、こちらが.NetFrameworkとして実装しているWebSocketsです。サポートOSがWindows8/WindowsServer2012となっておりWindows7はサポートしていません(コーディングはできるが、実行できない)。Windows8は持っていないので体験版を使用してVM上で試してみたい思います。

とりあえずチャットソフト。
とりあえずチャットソフトを作成。ClientWebSocketなので今回はクライアント版。サーバーはとりあえず以前作成したエコーサーバーを使用。

画面
Img20130307144817

動作画面

ソース

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

using System.Threading;
using System.Net.WebSockets;

namespace WsForm_WCF_ForWin8
{
    public partial class Form1 : Form
    {
        /// <summary>
        /// Send message buffer size.
        /// </summary>
        const int MessageBufferSize = 256;

        /// <summary>
        /// ClientWebSocket instance.
        /// </summary>
        ClientWebSocket _ws = null;

        public Form1()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Server connect.
        /// </summary>
        private async void Connect()
        {
            if (_ws == null)
            {
                _ws = new ClientWebSocket();
            }

            if (_ws.State != WebSocketState.Open)
            {
                await _ws.ConnectAsync(new Uri(textBox1.Text), CancellationToken.None);

                while (_ws.State == WebSocketState.Open)
                {
                    var buff = new ArraySegment<byte>(new byte[MessageBufferSize]);
                    var ret = await _ws.ReceiveAsync(buff, CancellationToken.None);
                    listBox1.Items.Add((new UTF8Encoding()).GetString(buff.Take(ret.Count).ToArray()));
                    listBox1.TopIndex = listBox1.Items.Count - 1;
                }
            }
        }

        /// <summary>
        /// Connect button.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            Connect();
        }

        /// <summary>
        /// Send message button.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button2_Click(object sender, EventArgs e)
        {
            var buff = new ArraySegment<byte>(Encoding.UTF8.GetBytes(textBox2.Text));
            if (_ws.State == WebSocketState.Open)
            {
                _ws.SendAsync(buff, WebSocketMessageType.Text, true, CancellationToken.None);
            }
        }

        /// <summary>
        /// Close websockets.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if ((_ws != null) && (_ws.State == WebSocketState.Open))
            {
                _ws.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);
            }
        }
    }
}

果たしてこれで良いのかどうかわかりませんが、細かいレベルの動作についてはおいおい。。。
尚、MSDNのサンプルを参考にしました。
WebSockets middle-tier sample using ClientWebSocket
http://code.msdn.microsoft.com/WebSockets-middle-tier-5b2972ce

全然違うコーディング。
これまでやってきたC#のWebSocketsのAPI(接続、送信、受信、接続断)はイベントハンドラを利用して処理をコーディングしましたが、ClientWebSocketはasync/awaitなAPIなので、コードが全然違います。Eventと違い非同期メソッドなので、その処理を待つ・処理後のコールバックなどは自分でコーディングする必要があります。コールバック的なものはawaitの直下の処理であり、この部分は別スレッドからのUIのアクセスにInvoke()が必要ありません。但し、awaitが使用できるのはasyncメソッド内だけだったり、awaitが指定できる処理はTaskを返すメソッドである必要があったり、色々考えて作る必要がありそうです。うーん、これは慣れるのに時間がかかりそう。。。

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

コメントを残す

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

CAPTCHA


This blog is kept spam free by WP-SpamFree.