Windows Phone 7 下 Socket(TCP) 与 PC 通讯
Windows Phone 7 下 Socket(TCP) 与 PC 通讯,使用 WP7 模拟器与 PC 上的 Simple TCP 服务进行通讯。
TCP 客户端主要实现 Socket 连接的建立、数据的发送与接收和关闭已经建立的 Socket。
1 using System; 2 using System.Net; 3 using System.Windows; 4 using System.Windows.Controls; 5 using System.Windows.Documents; 6 using System.Windows.Ink; 7 using System.Windows.Input; 8 using System.Windows.Media; 9 using System.Windows.Media.Animation; 10 using System.Windows.Shapes; 11 12 // 手动增加的 13 using System.Net.Sockets; 14 using System.Threading; 15 using System.Text; 16 17 namespace SocketClientTest 18 { 19 public class SocketClient 20 { 21 Socket socket = null; 22 23 // 当一个异步操作完成时, 用于通知的事件对象 24 static ManualResetEvent socketDone = new ManualResetEvent(false); 25 26 // 异步操作超过时间定义. 如果在此时间内未接收到回应, 则放弃此操作. 27 const int TIMEOUT_MILLISECONDS = 5000; 28 29 // 最大接收缓冲 30 const int MAX_BUFFER_SIZE = 2048; 31 32 // Socket 连接到指定端口的服务器 33 // hostName 服务器名称 34 // portNumber 连接端口 35 // 返回值: 连接结果返回的字符串 36 public string Connect(string hostName, int portNumber) 37 { 38 string result = string.Empty; 39 40 // 创建 DnsEndPoint. 服务器的端口传入此方法 41 DnsEndPoint hostEntry = new DnsEndPoint(hostName, portNumber); 42 43 socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 44 45 // 创建一个 SocketAsyncEventArgs 对象用于连接请求 46 SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs(); 47 socketEventArg.RemoteEndPoint = hostEntry; 48 49 // Inline event handler for the Completed event. 50 // Note: This event handler was implemented inline in order to make this method self-contained. 51 socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(delegate(object s, SocketAsyncEventArgs e) 52 { 53 result = e.SocketError.ToString(); 54 // 标识请求已经完成, 不阻塞 UI 线程 55 socketDone.Set(); 56 } 57 ); 58 59 socketDone.Reset(); 60 socket.ConnectAsync(socketEventArg); 61 socketDone.WaitOne(TIMEOUT_MILLISECONDS); 62 63 return result; 64 } 65 66 public string Send(string data) 67 { 68 string response = "Operation Timeout"; 69 70 if (socket != null) 71 { 72 // 创建 SocketAsyncEventArgs 对象、并设置对象属性 73 SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs(); 74 socketEventArg.RemoteEndPoint = socket.RemoteEndPoint; 75 socketEventArg.UserToken = null; 76 77 socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(delegate(object s, SocketAsyncEventArgs e) 78 { 79 response = e.SocketError.ToString(); 80 socketDone.Set(); 81 } 82 ); 83 84 // 将需要发送的数据送入发送缓冲区 85 byte[] payload = Encoding.UTF8.GetBytes(data); 86 socketEventArg.SetBuffer(payload, 0, payload.Length); 87 88 socketDone.Reset(); 89 socket.SendAsync(socketEventArg); 90 socketDone.WaitOne(TIMEOUT_MILLISECONDS); 91 } 92 else 93 { 94 response = "Socket is not initialized"; 95 } 96 97 return response; 98 } 99 100 public string Receive() 101 { 102 string response = "Operation Timeout"; 103 104 if (socket != null) 105 { 106 SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs(); 107 socketEventArg.RemoteEndPoint = socket.RemoteEndPoint; 108 socketEventArg.SetBuffer(new Byte[MAX_BUFFER_SIZE], 0, MAX_BUFFER_SIZE); 109 110 socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(delegate(object s, SocketAsyncEventArgs e) 111 { 112 if (e.SocketError == SocketError.Success) 113 { 114 // 从接收缓冲区得到数据 115 response = Encoding.UTF8.GetString(e.Buffer, e.Offset, e.BytesTransferred); 116 response = response.Trim('\0'); 117 } 118 else 119 { 120 response = e.SocketError.ToString(); 121 } 122 123 socketDone.Set(); 124 } 125 ); 126 127 socketDone.Reset(); 128 socket.ReceiveAsync(socketEventArg); 129 socketDone.WaitOne(TIMEOUT_MILLISECONDS); 130 } 131 else 132 { 133 response = "Socket is not initialized"; 134 } 135 136 return response; 137 } 138 139 /// <summary> 140 /// Closes the Socket connection and releases all associated resources 141 /// </summary> 142 public void Close() 143 { 144 if (socket != null) 145 { 146 socket.Close(); 147 } 148 } 149 } 150 }
对 TCP 客户端的使用如下:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Net; 5 using System.Windows; 6 using System.Windows.Controls; 7 using System.Windows.Documents; 8 using System.Windows.Input; 9 using System.Windows.Media; 10 using System.Windows.Media.Animation; 11 using System.Windows.Shapes; 12 using Microsoft.Phone.Controls; 13 14 /* 15 * 可以运行在 Windows Phone 7 模拟器上与 PC 进行 Socket 通讯。从 Simple TCP 服务获取相应的回应。 16 */ 17 18 namespace SocketClientTest 19 { 20 public partial class MainPage : PhoneApplicationPage 21 { 22 const int ECHO_PORT = 7; // 回应端口: 配合 PC 系统的 Simple TCP 服务使用,回应接收到的字符串 23 const int QOTD_PORT = 17; // 当日语录端口: 配合 PC 系统的 Simple TCP 服务使用 24 25 // 构造函数 26 public MainPage() 27 { 28 InitializeComponent(); 29 30 txtRemoteHost.Text = "yonghang-pc"; // 计算机名:可以从 桌面->计算名->属性中查看到 31 txtInput.Text = "Test socket 测试"; // 发送的字符串 32 } 33 34 private void btnEcho_Click(object sender, RoutedEventArgs e) 35 { 36 // 清空 log 37 ClearLog(); 38 39 // 确认输入是否有效 40 if (ValidateRemoteHostInput() && ValidateEditEchoInput()) 41 { 42 // 初始化 SocketClient 实例 43 SocketClient client = new SocketClient(); 44 45 // 开始连接 Echo Server 46 Log(String.Format("Connecting to server '{0}' over port {1} (echo) ...", txtRemoteHost.Text, ECHO_PORT), true); 47 string result = client.Connect(txtRemoteHost.Text, ECHO_PORT); 48 Log(result, false); 49 50 // 发送字符串到 Echo Server 51 Log(String.Format("Sending '{0}' to server ...", txtInput.Text), true); 52 result = client.Send(txtInput.Text); 53 Log(result, false); 54 55 // 接收来自 Echo Server 的回应 56 Log("Requesting Receive ...", true); 57 result = client.Receive(); 58 Log(result, false); 59 60 // 关闭 Socket 连接 61 client.Close(); 62 } 63 64 } 65 66 // 获取当日语录 67 private void btnGetQuote_Click(object sender, RoutedEventArgs e) 68 { 69 ClearLog(); 70 71 if (ValidateRemoteHostInput()) 72 { 73 SocketClient client = new SocketClient(); 74 75 Log(String.Format("Connecting to server '{0}' over port {1} (Quote of the Day) ...", txtRemoteHost.Text, QOTD_PORT), true); 76 string result = client.Connect(txtRemoteHost.Text, QOTD_PORT); 77 Log(result, false); 78 79 Log("Requesting Receive ...", true); 80 result = client.Receive(); 81 Log(result, false); 82 83 client.Close(); 84 } 85 } 86 87 // 判断是否有输入 88 private bool ValidateEditEchoInput() 89 { 90 if (String.IsNullOrWhiteSpace(txtInput.Text)) 91 { 92 MessageBox.Show("Please enter string to send."); 93 return false; 94 } 95 96 return true; 97 } 98 99 // 判断是否有输入 100 private bool ValidateRemoteHostInput() 101 { 102 if (String.IsNullOrWhiteSpace(txtRemoteHost.Text)) 103 { 104 MessageBox.Show("Please enter host name!"); 105 return false; 106 } 107 108 return true; 109 } 110 111 // 在 TextBox 中输出测试信息 112 private void Log(string message, bool isOutgoing) 113 { 114 string direction = (isOutgoing) ? ">> " : "<< "; 115 txtOutput.Text += Environment.NewLine + direction + message; 116 } 117 118 // 清空测试信息 119 private void ClearLog() 120 { 121 txtOutput.Text = String.Empty; 122 } 123 } 124 }