[C#][Silverlight] Silverlight使用Socket與視窗應用程式溝通

  • 6055
  • 0
  • 2011-06-20

[C#][Silverlight] Silverlight與視窗應用程式溝通

最近我想試試看實作HTTP伺服器在使用者電腦,讓使用者以網頁方式跟自己電腦上的HTTP伺服器作互動,藉此來操控應用程式等等的東西。因為是自行實作HTTP伺服器,也就是說只有簡單的HTTP標準能力,在互動上就稍嫌麻煩,因此我就想試試看Microsoft近年一直在推的Silverlight,Silverlight是網頁透過網頁外掛的方式呈現,可以取得Browser的資訊並且可以當作在客端電腦上互動的媒介,不然一般必須靠Java或Flash來達成。但是Silverlight的類別庫跟.Net Framework的一般類別庫是分開的,僅有簡單的Socket進行TCP通訊協定可以使用,以下是Socket在TCP模式下與本機的另外一隻Windows Form應用程式進行溝通的範例。

 

PS:由於Silverlight有安全考量的問題,如果直接使用下方範例一定會造成例外狀況,請參考[Socket 連線–Error Code 10013 嘗試存取通訊端被拒絕,因為存取權限不足。 解決方案]

 

[完整範例程式碼下載:SilverlightSocketDemo.zip]

 

※全文歡迎轉載但請註明出處,謝謝。※

 

未命名 - 1

 

因為Server端的寫法跟原本TcpListener的用法一樣,因此僅貼出Silverlight的程式碼,若要方便進行測試可以點擊上方連結下載完整程式碼。

 

    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
        }

        //非同步作業所要使用的資料。
        SocketAsyncEventArgs _AsyncEventArgs = new SocketAsyncEventArgs();
        Socket _Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            //由於部落格另外一篇文章是使用TCP來作範例,這邊也使用TCP來作示範。
            _AsyncEventArgs.SocketClientAccessPolicyProtocol = SocketClientAccessPolicyProtocol.Tcp;
            _AsyncEventArgs.RemoteEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 4525);
            _AsyncEventArgs.Completed += new EventHandler<SocketAsyncEventArgs>(AsyncEventArgs_Completed);
            _AsyncEventArgs.UserToken = _Socket;
            //開始Socket的非同步連線作業。
            _Socket.ConnectAsync(_AsyncEventArgs);
        }

        ManualResetEvent _Done = new ManualResetEvent(false);
        //非同步作業完畢之後引發此方法
        private void AsyncEventArgs_Completed(object sender, SocketAsyncEventArgs e)
        {
            //若事件資料顯示成功則執行
            if (e.SocketError == SocketError.Success)
            {
                //因為Connect、Receive、Send可以使用同一份非同步事件資料進行,所以也提供了方式查詢這次的擲回是做完哪件事情。
                switch (e.LastOperation)
                {
                    case SocketAsyncOperation.Connect:
                        {
                            //連線完成之後開始進行接收,這邊要特別注意非同步事件資料的緩衝區原本是null,
                            //若是不透過SetBuffer方法進行宣告就直接呼叫ReceiveAsync方法,會造成Socket直接關閉。
                            _AsyncEventArgs.SetBuffer(new Byte[1024], 0, 1024);
                            _Socket.ReceiveAsync(_AsyncEventArgs);
                            break;
                        }
                    case SocketAsyncOperation.Receive:
                        {
                            _Done.Reset();
                            this.Dispatcher.BeginInvoke(new Action(() =>
                            {
                                textBox1.Text += (Encoding.Unicode.GetString(e.Buffer, 0, e.BytesTransferred)) + "\r\n";
                                textBox1.Select(textBox1.Text.Length, 0);
                                _Done.Set();
                            }));
                            _Done.WaitOne();
                            //接收到伺服器端的資料之後我們在客端也回傳一份回應回去
                            String m_Message = String.Format("I got {0} byte(s).", e.BytesTransferred);
                            Byte[] m_MessageData = Encoding.Unicode.GetBytes(m_Message);
                            //這邊利用SetBuffer將要傳送的資料陣列丟進非同步作業資料裡面。
                            _AsyncEventArgs.SetBuffer(m_MessageData, 0, m_MessageData.Length);
                            //並且呼叫SendAsync方法進行非同步傳送。
                            _Socket.SendAsync(_AsyncEventArgs);
                            break;
                        }
                    case SocketAsyncOperation.Send:
                        {
                            _AsyncEventArgs.SetBuffer(new Byte[1024], 0, 1024);
                            _Socket.ReceiveAsync(_AsyncEventArgs);
                            break;
                        }
                }
            }
                //失敗則顯示例外狀況。
            else
                this.Dispatcher.BeginInvoke(new Action(() =>
                            { MessageBox.Show(new SocketException((int)e.SocketError).Message); }));
        }
    }

分享