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客户端向服务器端发送消息和接收消息的功能。

先来看看演示的效果
(1)Windows Phone 7客户端客户端的实现。
MainPage.xaml
 1 <phone:PhoneApplicationPage 
2 x:Class="SocketTest.MainPage"
3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
5 xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
6 xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
7 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
8 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
9 mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
10 FontFamily="{StaticResource PhoneFontFamilyNormal}"
11 FontSize="{StaticResource PhoneFontSizeNormal}"
12 Foreground="{StaticResource PhoneForegroundBrush}"
13 SupportedOrientations="Portrait" Orientation="Portrait"
14 shell:SystemTray.IsVisible="True">
15
16 <Grid x:Name="LayoutRoot" Background="Transparent">
17 <Grid.RowDefinitions>
18 <RowDefinition Height="Auto"/>
19 <RowDefinition Height="*"/>
20 </Grid.RowDefinitions>
21
22 <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
23 <TextBlock x:Name="ApplicationTitle" Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}"/>
24 <TextBlock x:Name="PageTitle" Text="Socket测试" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
25 </StackPanel>
26
27 <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
28
29 <TextBlock FontSize="30" Text="主机IP:" Margin="12,23,0,540" HorizontalAlignment="Left" Width="99" />
30 <TextBox x:Name="Host" InputScope="Digits" HorizontalAlignment="Stretch" Text="192.168.1.102" Margin="110,6,0,523" />
31 <TextBlock FontSize="30" Text="端口号:" Margin="9,102,345,451" />
32 <TextBox x:Name="Port" InputScope="Digits"
33 HorizontalAlignment="Stretch"
34 Text="8888" Margin="110,90,0,433" />
35 <TextBlock FontSize="30" Text="发送的消息内容:" Margin="6,180,157,374" />
36 <TextBox x:Name="Message"
37 HorizontalAlignment="Stretch" Margin="-6,226,6,300" />
38 <Button x:Name="SendButton"
39 Content="发送"
40 Click="SendButton_Click" Margin="0,509,12,6" />
41 <ListBox Height="190" HorizontalAlignment="Left" Margin="-4,313,0,0" Name="listBox1" VerticalAlignment="Top" Width="460" />
42 </Grid>
43 </Grid>
44
45 </phone:PhoneApplicationPage>
cs文件
  1 using System;
2 using System.Net;
3 using System.Windows;
4 using Microsoft.Phone.Controls;
5 using System.Text;
6 using System.Net.Sockets;
7
8 namespace SocketTest
9 {
10 public partial class MainPage : PhoneApplicationPage
11 {
12 public MainPage()
13 {
14 InitializeComponent();
15 }
16
17 private void SendButton_Click(object sender, RoutedEventArgs e)
18 {
19 // 判断是否已经输入了IP地址和端口
20 if (string.IsNullOrEmpty(Host.Text) || string.IsNullOrEmpty(Port.Text))
21 {
22 MessageBox.Show("麻烦输入以下主机IP和端口号,谢谢!");
23 return;
24 }
25 //主机IP地址
26 string host = Host.Text.Trim();
27 //端口号
28 int port = Convert.ToInt32(Port.Text.Trim());
29 //建立一个终结点对像
30 DnsEndPoint hostEntry = new DnsEndPoint(host, port);
31 //创建一个Socket对象
32 Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
33 //创建一个Socket异步事件参数
34 SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs();
35 //将消息内容转化为发送的byte[]格式
36 byte[] buffer = Encoding.UTF8.GetBytes(Message.Text);
37 //将发送内容的信息存放进Socket异步事件参数中
38 socketEventArg.SetBuffer(buffer, 0, buffer.Length);
39 //注册Socket完成事件
40 socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(SocketAsyncEventArgs_Completed);
41 //设置Socket异步事件参数的Socket远程终结点
42 socketEventArg.RemoteEndPoint = hostEntry;
43 //将定义好的Socket对象赋值给Socket异步事件参数的运行实例属性
44 socketEventArg.UserToken = sock;
45
46 try
47 {
48 //运行Socket
49 sock.ConnectAsync(socketEventArg);
50 }
51 catch (SocketException ex)
52 {
53 throw new SocketException((int)ex.ErrorCode);
54 }
55
56 }
57
58 private void SocketAsyncEventArgs_Completed(object sender, SocketAsyncEventArgs e)
59 {
60 // 检查是否发送出错
61 if (e.SocketError != SocketError.Success)
62 {
63 if (e.SocketError == SocketError.ConnectionAborted)
64 {
65 Dispatcher.BeginInvoke(() => MessageBox.Show("连接超时请重试! "
66 + e.SocketError));
67 }
68 else if (e.SocketError == SocketError.ConnectionRefused)
69 {
70 Dispatcher.BeginInvoke(() => MessageBox.Show("服务器端问启动"
71 + e.SocketError));
72 }
73 else
74 {
75 Dispatcher.BeginInvoke(() => MessageBox.Show("出错了"
76 + e.SocketError));
77 }
78
79 //关闭连接清理资源
80 if (e.UserToken != null)
81 {
82 Socket sock = e.UserToken as Socket;
83 sock.Shutdown(SocketShutdown.Both);
84 sock.Close();
85 }
86 return;
87
88 }
89
90 //检查Socket的当前最后的一个操作
91 switch (e.LastOperation)
92 {
93 //如果最后的一个操作是连接,那么下一步处理就是发送消息。
94 case SocketAsyncOperation.Connect:
95 if (e.UserToken != null)
96 {
97 //获取运行中的Socket对象
98 Socket sock = e.UserToken as Socket;
99 //开始发送
100 bool completesAsynchronously = sock.SendAsync(e);
101 //检查socket发送是否被挂起,如果被挂起将继续进行处理
102 if (!completesAsynchronously)
103 {
104 SocketAsyncEventArgs_Completed(e.UserToken, e);
105 }
106 };
107 break;
108 //如果最后的一个操作是发送,那么显示刚才发送成功的消息,然后开始下一步处理就是接收消息。
109 case SocketAsyncOperation.Send:
110 //将已成功发送的消息内容绑定到listBox1控件中
111 Dispatcher.BeginInvoke(() =>
112 {
113 listBox1.Items.Add("客户端" + DateTime.Now.ToShortTimeString() + "发送的消息 :" + Message.Text);
114 }
115 );
116 if (e.UserToken != null)
117 {
118 //获取运行中的Socket对象
119 Socket sock = e.UserToken as Socket;
120 //开始接收服务器端的消息
121 bool completesAsynchronously = sock.ReceiveAsync(e);
122 //检查socket发送是否被挂起,如果被挂起将继续进行处理
123 if (!completesAsynchronously)
124 {
125 SocketAsyncEventArgs_Completed(e.UserToken, e);
126 }
127 }
128 break;
129 //如果是最后的一个操作时接收,那么显示接收到的消息内容,并清理资源。
130 case SocketAsyncOperation.Receive:
131 if (e.UserToken != null)
132 {
133 //获取接收到的消息,并转化为字符串
134 string dataFromServer = Encoding.UTF8.GetString(e.Buffer, 0, e.BytesTransferred);
135 //获取运行中的Socket对象
136 Socket sock = e.UserToken as Socket;
137 //将接收到的消息内容绑定到listBox1控件中
138 Dispatcher.BeginInvoke(() =>
139 {
140 listBox1.Items.Add("服务器端" + DateTime.Now.ToShortTimeString() + "传过来的消息:" + dataFromServer);
141 });
142 }
143 break;
144 }
145 }
146 }
147 }
(2) Socket服务器端的实现,使用Windows的控制台程序。
  1 using System;
2 using System.Linq;
3 using System.Net;
4 using System.Net.Sockets;
5 using System.Text;
6 using System.Threading;
7
8 namespace SocketServer
9 {
10 static class Program
11 {
12
13 private static AutoResetEvent _flipFlop = new AutoResetEvent(false);
14
15 static void Main(string[] args)
16 {
17 //创建socket,使用的是TCP协议,如果用UDP协议,则要用SocketType.Dgram类型的Socket
18 Socket listener = new Socket(AddressFamily.InterNetwork,
19 SocketType.Stream,
20 ProtocolType.Tcp);
21
22 //创建终结点EndPoint 取当前主机的ip
23 IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
24 //把ip和端口转化为IPEndpoint实例,端口号取8888
25 IPEndPoint localEP = new IPEndPoint(ipHostInfo.AddressList.First(), 8888);
26
27 Console.WriteLine("本地的IP地址和端口是 : {0}", localEP);
28
29 try
30 {
31 //绑定EndPoint对像(8888端口和ip地址)
32 listener.Bind(localEP);
33 //开始监听
34 listener.Listen(10);
35 //一直循环接收客户端的消息
36 while (true)
37 {
38 Console.WriteLine("等待Windows Phone客户端的连接...");
39 //开始接收下一个连接
40 listener.BeginAccept(AcceptCallback, listener);
41 //开始线程等待
42 _flipFlop.WaitOne();
43 }
44 }
45 catch (Exception e)
46 {
47 Console.WriteLine(e.ToString());
48 }
49
50 }
51
52 /// <summary>
53 /// 接收返回事件处理
54 /// </summary>
55 /// <param name="ar"></param>
56 private static void AcceptCallback(IAsyncResult ar)
57 {
58 Socket listener = (Socket)ar.AsyncState;
59 Socket socket = listener.EndAccept(ar);
60
61 Console.WriteLine("连接到Windows Phone客户端。");
62
63 _flipFlop.Set();
64
65 //开始接收,传递StateObject对象过去
66 var state = new StateObject();
67 state.Socket = socket;
68 socket.BeginReceive(state.Buffer,
69 ,
70 StateObject.BufferSize,
71 ,
72 ReceiveCallback,
73 state);
74 }
75
76 private static void ReceiveCallback(IAsyncResult ar)
77 {
78 StateObject state = (StateObject)ar.AsyncState;
79 Socket socket = state.Socket;
80
81 // 读取客户端socket发送过来的数据
82 int read = socket.EndReceive(ar);
83
84 // 如果成功读取了客户端socket发送过来的数据
85 if (read > 0)
86 {
87 //获取客户端的消息,转化为字符串格式
88 string chunk = Encoding.UTF8.GetString(state.Buffer, 0, read);
89 state.StringBuilder.Append(chunk);
90
91 if (state.StringBuilder.Length > 0)
92 {
93 string result = state.StringBuilder.ToString();
94 Console.WriteLine("收到客户端传过来的消息: {0}", result);
95 //发送数据信息给客户端
96 Send(socket, result);
97 }
98 }
99 }
100
101 /// <summary>
102 /// 返回客户端数据
103 /// </summary>
104 /// <param name="handler"></param>
105 /// <param name="data"></param>
106 private static void Send(Socket handler, String data)
107 {
108
109 //将消息内容转化为发送的byte[]格式
110 byte[] byteData = Encoding.UTF8.GetBytes(data);
111
112 //发送消息到Windows Phone客户端
113 handler.BeginSend(byteData, 0, byteData.Length, 0,
114 new AsyncCallback(SendCallback), handler);
115 }
116
117 private static void SendCallback(IAsyncResult ar)
118 {
119 try
120 {
121 Socket handler = (Socket)ar.AsyncState;
122 // 完成发送消息到Windows Phone客户端
123 int bytesSent = handler.EndSend(ar);
124 if (bytesSent > 0)
125 {
126 Console.WriteLine("发送成功!");
127 }
128 }
129 catch (Exception e)
130 {
131 Console.WriteLine(e.ToString());
132 }
133 }
134 }
135
136 public class StateObject
137 {
138 public Socket Socket;
139 public StringBuilder StringBuilder = new StringBuilder();
140 public const int BufferSize = 10;
141 public byte[] Buffer = new byte[BufferSize];
142 public int TotalSize;
143 }
144 }
(3)我个人感觉服务端这个异步接受有点难,所以自己偷懒简化了一下
 1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Net;
6 using System.Net.Sockets;
7
8 namespace SocketTestServer
9 {
10 class Program
11 {
12
13 static void Main(string[] args)
14 {
15 Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
16 try
17 {
18 IPHostEntry ipInfo = Dns.Resolve(Dns.GetHostName());
19 IPEndPoint localEP = new IPEndPoint(ipInfo.AddressList.First(), 8888);
20 Console.WriteLine("本地监听IP与端口为:" + localEP);
21 socket.Bind(localEP);
22 socket.Listen(1);
23 while (true)
24 {
25 Console.WriteLine("等待连接中...");
26 Socket newSocket = socket.Accept();
27 Console.WriteLine("连接到Windows Phone 7 客户端...");
28 byte [] clientDate= new byte[1024];
29 int clientDateLength=newSocket.Receive(clientDate);
30 Console.WriteLine("客户端传来消息:" + Encoding.UTF8.GetString(clientDate, 0, clientDateLength));
31 if (Encoding.UTF8.GetString(clientDate, 0, clientDateLength)=="退出")
32 {
33 break;
34 }
35 Console.WriteLine("开始向客户端发送消息...");
36 byte[] serverDate = Encoding.UTF8.GetBytes("你好啊!");
37 newSocket.Send(serverDate);
38 Console.WriteLine("发送完毕!");
39 }
40 }
41 catch (Exception ex)
42 {
43 Console.WriteLine(ex.Message);
44 }
45 finally
46 {
47 socket.Close();
48 }
49 }
50 }
51 }

原文地址:https://www.cnblogs.com/lyghost/p/2418925.html