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; } } }