芒果更新的Windows Phone 7.1版本的API提供了Socket程式設計的接口,這給Windows Phone 7的網絡開發又添加了一把利器,對于Windows Phone 7上的聊天軟體開發是一件非常happy的事情。下面用一個小例子來示範一下Windows Phone 7上的Socket程式設計。用Windows Phone 7上的用戶端程式作為Socket用戶端,Windows控制台程式作為伺服器端,ip取你電腦本機的ip,端口号用8888,實作了Windows Phone 7用戶端向伺服器端發送消息和接收消息的功能。
先來看看示範的效果
(1) Windows Phone 7用戶端用戶端的實作。
MainPage.xaml
<phone:PhoneApplicationPage
x:Class="SocketTest.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
shell:SystemTray.IsVisible="True">
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock x:Name="ApplicationTitle" Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="Socket測試" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<TextBlock FontSize="30" Text="主機IP:" Margin="12,23,0,540" HorizontalAlignment="Left" Width="99" />
<TextBox x:Name="Host" InputScope="Digits" HorizontalAlignment="Stretch" Text="192.168.1.102" Margin="110,6,0,523" />
<TextBlock FontSize="30" Text="端口号:" Margin="9,102,345,451" />
<TextBox x:Name="Port" InputScope="Digits"
HorizontalAlignment="Stretch"
Text="8888" Margin="110,90,0,433" />
<TextBlock FontSize="30" Text="發送的消息内容:" Margin="6,180,157,374" />
<TextBox x:Name="Message"
HorizontalAlignment="Stretch" Margin="-6,226,6,300" />
<Button x:Name="SendButton"
Content="發送"
Click="SendButton_Click" Margin="0,509,12,6" />
<ListBox Height="190" HorizontalAlignment="Left" Margin="-4,313,0,0" Name="listBox1" VerticalAlignment="Top" Width="460" />
</Grid>
</Grid>
</phone:PhoneApplicationPage>
cs頁面
using System;
using System.Net;
using System.Windows;
using Microsoft.Phone.Controls;
using System.Text;
using System.Net.Sockets;
namespace SocketTest
{
public partial class MainPage : PhoneApplicationPage
{
public MainPage()
{
InitializeComponent();
}
private void SendButton_Click(object sender, RoutedEventArgs e)
// 判斷是否已經輸入了IP位址和端口
if (string.IsNullOrEmpty(Host.Text) || string.IsNullOrEmpty(Port.Text))
{
MessageBox.Show("麻煩輸入以下主機IP和端口号,謝謝!");
return;
}
//主機IP位址
string host = Host.Text.Trim();
//端口号
int port = Convert.ToInt32(Port.Text.Trim());
//建立一個終結點對像
DnsEndPoint hostEntry = new DnsEndPoint(host, port);
//建立一個Socket對象
Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//建立一個Socket異步事件參數
SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs();
//将消息内容轉化為發送的byte[]格式
byte[] buffer = Encoding.UTF8.GetBytes(Message.Text);
//将發送内容的資訊存放進Socket異步事件參數中
socketEventArg.SetBuffer(buffer, 0, buffer.Length);
//注冊Socket完成事件
socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(SocketAsyncEventArgs_Completed);
//設定Socket異步事件參數的Socket遠端終結點
socketEventArg.RemoteEndPoint = hostEntry;
//将定義好的Socket對象指派給Socket異步事件參數的運作執行個體屬性
socksocketEventArg.UserToken = sock;
try
//運作Socket
sock.ConnectAsync(socketEventArg);
catch (SocketException ex)
throw new SocketException((int)ex.ErrorCode);
private void SocketAsyncEventArgs_Completed(object sender, SocketAsyncEventArgs e)
// 檢查是否發送出錯
if (e.SocketError != SocketError.Success)
if (e.SocketError == SocketError.ConnectionAborted)
{
Dispatcher.BeginInvoke(() => MessageBox.Show("連接配接逾時請重試! "
+ e.SocketError));
}
else if (e.SocketError == SocketError.ConnectionRefused)
Dispatcher.BeginInvoke(() => MessageBox.Show("伺服器端問啟動"
+ e.SocketError));
else
Dispatcher.BeginInvoke(() => MessageBox.Show("出錯了"
//關閉連接配接清理資源
if (e.UserToken != null)
Socket sock = e.UserToken as Socket;
sock.Shutdown(SocketShutdown.Both);
sock.Close();
//檢查Socket的目前最後的一個操作
switch (e.LastOperation)
//如果最後的一個操作是連接配接,那麼下一步處理就是發送消息。
case SocketAsyncOperation.Connect:
if (e.UserToken != null)
{
//擷取運作中的Socket對象
Socket sock = e.UserToken as Socket;
//開始發送
bool completesAsynchronously = sock.SendAsync(e);
//檢查socket發送是否被挂起,如果被挂起将繼續進行處理
if (!completesAsynchronously)
{
SocketAsyncEventArgs_Completed(e.UserToken, e);
}
};
break;
//如果最後的一個操作是發送,那麼顯示剛才發送成功的消息,然後開始下一步處理就是接收消息。
case SocketAsyncOperation.Send:
//将已成功發送的消息内容綁定到listBox1控件中
Dispatcher.BeginInvoke(() =>
listBox1.Items.Add("用戶端" + DateTime.Now.ToShortTimeString() + "發送的消息 :" + Message.Text);
);
//開始接收伺服器端的消息
bool completesAsynchronously = sock.ReceiveAsync(e);
}
//如果是最後的一個操作時接收,那麼顯示接收到的消息内容,并清理資源。
case SocketAsyncOperation.Receive:
//擷取接收到的消息,并轉化為字元串
string dataFromServer = Encoding.UTF8.GetString(e.Buffer, 0, e.BytesTransferred);
//将接收到的消息内容綁定到listBox1控件中
Dispatcher.BeginInvoke(() =>
listBox1.Items.Add("伺服器端" + DateTime.Now.ToShortTimeString() + "傳過來的消息:" + dataFromServer);
});
break;
}
}
(2) Socket伺服器端的實作,使用Windows的控制台程式。
using System.Linq;
using System.Threading;
namespace SocketServer
static class Program
private static AutoResetEvent _flipFlop = new AutoResetEvent(false);
static void Main(string[] args)
//建立socket,使用的是TCP協定,如果用UDP協定,則要用SocketType.Dgram類型的Socket
Socket listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
//建立終結點EndPoint 取目前主機的ip
IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
//把ip和端口轉化為IPEndpoint執行個體,端口号取8888
IPEndPoint localEP = new IPEndPoint(ipHostInfo.AddressList.First(), 8888);
Console.WriteLine("本地的IP位址和端口是 : {0}", localEP);
//綁定EndPoint對像(8888端口和ip位址)
listener.Bind(localEP);
//開始監聽
listener.Listen(10);
//一直循環接收用戶端的消息
while (true)
Console.WriteLine("等待Windows Phone用戶端的連接配接...");
//開始接收下一個連接配接
listener.BeginAccept(AcceptCallback, listener);
//開始線程等待
_flipFlop.WaitOne();
catch (Exception e)
Console.WriteLine(e.ToString());
/// <summary>
/// 接收傳回事件處理
/// </summary>
/// <param name="ar"></param>
private static void AcceptCallback(IAsyncResult ar)
Socket listener = (Socket)ar.AsyncState;
Socket socket = listener.EndAccept(ar);
Console.WriteLine("連接配接到Windows Phone用戶端。");
_flipFlop.Set();
//開始接收,傳遞StateObject對象過去
var state = new StateObject();
state.Socket = socket;
socket.BeginReceive(state.Buffer,
,
StateObject.BufferSize,
ReceiveCallback,
state);
private static void ReceiveCallback(IAsyncResult ar)
StateObject state = (StateObject)ar.AsyncState;
Socket socket = state.Socket;
// 讀取用戶端socket發送過來的資料
int read = socket.EndReceive(ar);
// 如果成功讀取了用戶端socket發送過來的資料
if (read > 0)
//擷取用戶端的消息,轉化為字元串格式
string chunk = Encoding.UTF8.GetString(state.Buffer, 0, read);
state.StringBuilder.Append(chunk);
if (state.StringBuilder.Length > 0)
string result = state.StringBuilder.ToString();
Console.WriteLine("收到用戶端傳過來的消息: {0}", result);
//發送資料資訊給用戶端
Send(socket, result);
/// 傳回用戶端資料
/// <param name="handler"></param>
/// <param name="data"></param>
private static void Send(Socket handler, String data)
//将消息内容轉化為發送的byte[]格式
byte[] byteData = Encoding.UTF8.GetBytes(data);
//發送消息到Windows Phone用戶端
handler.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), handler);
private static void SendCallback(IAsyncResult ar)
Socket handler = (Socket)ar.AsyncState;
// 完成發送消息到Windows Phone用戶端
int bytesSent = handler.EndSend(ar);
if (bytesSent > 0)
Console.WriteLine("發送成功!");
public class StateObject
public Socket Socket;
public StringBuilder StringBuilder = new StringBuilder();
public const int BufferSize = 10;
public byte[] Buffer = new byte[BufferSize];
public int TotalSize;
本文轉自linzheng 51CTO部落格,原文連結:http://blog.51cto.com/linzheng/1078573