zoukankan      html  css  js  c++  java
  • 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 }

  • 相关阅读:
    [算法]最长的可整合数组的长度
    [算法]在行列都排好序的矩阵中找数
    [算法]在数组中找到出现次数大于N/K的数
    [算法]需要排序的最短子数组长度
    [算法]找到无序数组中最小的K个数
    [算法]“之”字形打印矩阵
    [java]final关键字、finally关键字与finalize()方法
    [算法]旋转矩阵问题(Spiral Matrix)
    [算法]位运算问题之三(实现加减乘除)
    [IDE]Intellij Idea学习整理
  • 原文地址:https://www.cnblogs.com/lyghost/p/2418925.html
Copyright © 2011-2022 走看看