Windows Phone 7 网络编程之使用Socket(芒果更新)

       芒果更新的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客户端向服务器端发送消息和接收消息的功能。
先来看看演示的效果
Windows Phone 7 网络编程之使用Socket(芒果更新)Windows Phone 7 网络编程之使用Socket(芒果更新)
(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异步事件参数的运行实例属性
socketEventArg.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( " 出错了 "
+ e.SocketError));
}

// 关闭连接清理资源
if (e.UserToken != null )
{
Socket sock
= e.UserToken as Socket;
sock.Shutdown(SocketShutdown.Both);
sock.Close();
}
return ;

}

// 检查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);
}
);
if (e.UserToken != null )
{
// 获取运行中的Socket对象
Socket sock = e.UserToken as Socket;
// 开始接收服务器端的消息
bool completesAsynchronously = sock.ReceiveAsync(e);
// 检查socket发送是否被挂起,如果被挂起将继续进行处理
if ( ! completesAsynchronously)
{
SocketAsyncEventArgs_Completed(e.UserToken, e);
}
}
break ;
// 如果是最后的一个操作时接收,那么显示接收到的消息内容,并清理资源。
case SocketAsyncOperation.Receive:
if (e.UserToken != null )
{
// 获取接收到的消息,并转化为字符串
string dataFromServer = Encoding.UTF8.GetString(e.Buffer, 0 , e.BytesTransferred);
// 获取运行中的Socket对象
Socket sock = e.UserToken as Socket;
// 将接收到的消息内容绑定到listBox1控件中
Dispatcher.BeginInvoke(() =>
{
listBox1.Items.Add(
" 服务器端 " + DateTime.Now.ToShortTimeString() + " 传过来的消息: " + dataFromServer);
});
}
break ;
}
}
}
}
(2)       Socket服务器端的实现,使用Windows的控制台程序。
   
     
using System;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
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);

try
{
// 绑定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,
0 ,
StateObject.BufferSize,
0 ,
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);
}
}
}


/// <summary>
/// 返回客户端数据
/// </summary>
/// <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)
{
try
{
Socket handler
= (Socket)ar.AsyncState;
// 完成发送消息到Windows Phone客户端
int bytesSent = handler.EndSend(ar);
if (bytesSent > 0 )
{
Console.WriteLine(
" 发送成功! " );
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
}

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;
}
}
 
ok了。。。晚安!

你可能感兴趣的:(windows phone)