Windows Phone 7 下 Socket(TCP) 與 PC 通訊,使用 WP7 模擬器與 PC 上的 Simple TCP 服務進行通訊。
TCP 用戶端主要實現 Socket 串連的建立、資料的發送與接收和關閉已經建立的 Socket。
using System;using System.Net;using System.Windows;using System.Windows.Controls;using System.Windows.Documents;using System.Windows.Ink;using System.Windows.Input;using System.Windows.Media;using System.Windows.Media.Animation;using System.Windows.Shapes;// 手動增加的using System.Net.Sockets;using System.Threading;using System.Text;namespace SocketClientTest{ public class SocketClient { Socket socket = null; // 當一個非同步作業完成時, 用於通知的事件對象 static ManualResetEvent socketDone = new ManualResetEvent(false); // 非同步作業超過時間定義. 如果在此時間內未接收到回應, 則放棄此操作. const int TIMEOUT_MILLISECONDS = 5000; // 最大接收緩衝 const int MAX_BUFFER_SIZE = 2048; // Socket 串連到指定連接埠的伺服器 // hostName 伺服器名稱 // portNumber 串連連接埠 // 傳回值: 串連結果返回的字串 public string Connect(string hostName, int portNumber) { string result = string.Empty; // 建立 DnsEndPoint. 伺服器的連接埠傳入此方法 DnsEndPoint hostEntry = new DnsEndPoint(hostName, portNumber); socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // 建立一個 SocketAsyncEventArgs 對象用於串連請求 SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs(); socketEventArg.RemoteEndPoint = hostEntry; // Inline event handler for the Completed event. // Note: This event handler was implemented inline in order to make this method self-contained. socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(delegate(object s, SocketAsyncEventArgs e) { result = e.SocketError.ToString(); // 標識請求已經完成, 不阻塞 UI 線程 socketDone.Set(); } ); socketDone.Reset(); socket.ConnectAsync(socketEventArg); socketDone.WaitOne(TIMEOUT_MILLISECONDS); return result; } public string Send(string data) { string response = "Operation Timeout"; if (socket != null) { // 建立 SocketAsyncEventArgs 對象、並設定對象屬性 SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs(); socketEventArg.RemoteEndPoint = socket.RemoteEndPoint; socketEventArg.UserToken = null; socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(delegate(object s, SocketAsyncEventArgs e) { response = e.SocketError.ToString(); socketDone.Set(); } ); // 將需要發送的資料送入發送緩衝區 byte[] payload = Encoding.UTF8.GetBytes(data); socketEventArg.SetBuffer(payload, 0, payload.Length); socketDone.Reset(); socket.SendAsync(socketEventArg); socketDone.WaitOne(TIMEOUT_MILLISECONDS); } else { response = "Socket is not initialized"; } return response; } public string Receive() { string response = "Operation Timeout"; if (socket != null) { SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs(); socketEventArg.RemoteEndPoint = socket.RemoteEndPoint; socketEventArg.SetBuffer(new Byte[MAX_BUFFER_SIZE], 0, MAX_BUFFER_SIZE); socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(delegate(object s, SocketAsyncEventArgs e) { if (e.SocketError == SocketError.Success) { // 從接收緩衝區得到資料 response = Encoding.UTF8.GetString(e.Buffer, e.Offset, e.BytesTransferred); response = response.Trim('\0'); } else { response = e.SocketError.ToString(); } socketDone.Set(); } ); socketDone.Reset(); socket.ReceiveAsync(socketEventArg); socketDone.WaitOne(TIMEOUT_MILLISECONDS); } else { response = "Socket is not initialized"; } return response; } /// <summary> /// Closes the Socket connection and releases all associated resources /// </summary> public void Close() { if (socket != null) { socket.Close(); } } }}
對 TCP 用戶端的使用如下:
using System;using System.Collections.Generic;using System.Linq;using System.Net;using System.Windows;using System.Windows.Controls;using System.Windows.Documents;using System.Windows.Input;using System.Windows.Media;using System.Windows.Media.Animation;using System.Windows.Shapes;using Microsoft.Phone.Controls;/* * 可以運行在 Windows Phone 7 模擬器上與 PC 進行 Socket 通訊。從 Simple TCP 服務擷取相應的回應。*/namespace SocketClientTest{ public partial class MainPage : PhoneApplicationPage { const int ECHO_PORT = 7; // 回應連接埠: 配合 PC 系統的 Simple TCP 服務使用,回應接收到的字串 const int QOTD_PORT = 17; // 當日語錄連接埠: 配合 PC 系統的 Simple TCP 服務使用 // 建構函式 public MainPage() { InitializeComponent(); txtRemoteHost.Text = "yonghang-pc"; // 電腦名稱:可以從 案頭->計算名->屬性中查看到 txtInput.Text = "Test socket 測試"; // 發送的字串 } private void btnEcho_Click(object sender, RoutedEventArgs e) { // 清空 log ClearLog(); // 確認輸入是否有效 if (ValidateRemoteHostInput() && ValidateEditEchoInput()) { // 初始化 SocketClient 執行個體 SocketClient client = new SocketClient(); // 開始串連 Echo Server Log(String.Format("Connecting to server '{0}' over port {1} (echo) ...", txtRemoteHost.Text, ECHO_PORT), true); string result = client.Connect(txtRemoteHost.Text, ECHO_PORT); Log(result, false); // 發送字串到 Echo Server Log(String.Format("Sending '{0}' to server ...", txtInput.Text), true); result = client.Send(txtInput.Text); Log(result, false); // 接收來自 Echo Server 的回應 Log("Requesting Receive ...", true); result = client.Receive(); Log(result, false); // 關閉 Socket 串連 client.Close(); } } // 擷取當日語錄 private void btnGetQuote_Click(object sender, RoutedEventArgs e) { ClearLog(); if (ValidateRemoteHostInput()) { SocketClient client = new SocketClient(); Log(String.Format("Connecting to server '{0}' over port {1} (Quote of the Day) ...", txtRemoteHost.Text, QOTD_PORT), true); string result = client.Connect(txtRemoteHost.Text, QOTD_PORT); Log(result, false); Log("Requesting Receive ...", true); result = client.Receive(); Log(result, false); client.Close(); } } // 判斷是否有輸入 private bool ValidateEditEchoInput() { if (String.IsNullOrWhiteSpace(txtInput.Text)) { MessageBox.Show("Please enter string to send."); return false; } return true; } // 判斷是否有輸入 private bool ValidateRemoteHostInput() { if (String.IsNullOrWhiteSpace(txtRemoteHost.Text)) { MessageBox.Show("Please enter host name!"); return false; } return true; } // 在 TextBox 中輸出測試資訊 private void Log(string message, bool isOutgoing) { string direction = (isOutgoing) ? ">> " : "<< "; txtOutput.Text += Environment.NewLine + direction + message; } // 清空測試資訊 private void ClearLog() { txtOutput.Text = String.Empty; } }}