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