介紹
重新想象 Windows 8 Store Apps 之 通訊
Socket - Tcp Demo
Socket - 實現一個自訂的 http server
Socket - Udp Demo
樣本
1、示範 socket tcp 的應用(本例既做服務端又做用戶端)
Communication/Socket/TcpDemo.xaml
<Page x:Class="XamlDemo.Communication.Socket.TcpDemo" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:XamlDemo.Communication.Socket" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="Transparent"> <StackPanel Margin="120 0 0 0" Orientation="Horizontal"> <StackPanel> <Button Name="btnStartListener" Content="start a socket listener" Click="btnStartListener_Click" /> <Button Name="btnConnectListener" Content="connect to the socket listener" Click="btnConnectListener_Click" Margin="0 10 0 0" /> <Button Name="btnSendData" Content="send data" Click="btnSendData_Click" Margin="0 10 0 0" /> <Button Name="btnCloseSocket" Content="close server socket and client socket" Click="btnCloseSocket_Click" Margin="0 10 0 0" /> </StackPanel> <TextBlock Name="lblMsg" FontSize="14.667" TextWrapping="Wrap" Margin="20 0 0 0" /> </StackPanel> </Grid></Page>
Communication/Socket/TcpDemo.xaml.cs
/* * 示範 socket tcp 的應用(本例既做服務端又做用戶端) * * 通過 StreamSocketListener 實現 tcp 通訊的服務端的 socket 監聽 * 通過 StreamSocket 實現 tcp 通訊的用戶端 socket * * 註:需要在 Package.appxmanifest 中增加配置 <Capability Name="privateNetworkClientServer" /> */ using System;using Windows.Networking;using Windows.Networking.Sockets;using Windows.Storage.Streams;using Windows.UI.Core;using Windows.UI.Xaml;using Windows.UI.Xaml.Controls; namespace XamlDemo.Communication.Socket{ public sealed partial class TcpDemo : Page { /// <summary> /// 服務端 socket /// </summary> private StreamSocketListener _listener; /// <summary> /// 用戶端 socket /// </summary> private StreamSocket _client; /// <summary> /// 用戶端向服務端發送資料時的 DataWriter /// </summary> private DataWriter _writer; public TcpDemo() { this.InitializeComponent(); } // 在服務端啟動一個 socket 監聽 private async void btnStartListener_Click(object sender, RoutedEventArgs e) { // 執行個體化一個 socket 監聽對象 _listener = new StreamSocketListener(); // 監聽在接收到一個串連後所觸發的事件 _listener.ConnectionReceived += _listener_ConnectionReceived; try { // 在指定的連接埠上啟動 socket 監聽 await _listener.BindServiceNameAsync("2211"); lblMsg.Text += "已經在原生 2211 連接埠啟動了 socket(tcp) 監聽"; lblMsg.Text += Environment.NewLine; } catch (Exception ex) { SocketErrorStatus errStatus = SocketError.GetStatus(ex.HResult); lblMsg.Text += "errStatus: " + errStatus.ToString(); lblMsg.Text += Environment.NewLine; lblMsg.Text += ex.ToString(); lblMsg.Text += Environment.NewLine; } } // socket 監聽接收到一個串連後 async void _listener_ConnectionReceived(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args) { // 執行個體化一個 DataReader,用於讀取資料 DataReader reader = new DataReader(args.Socket.InputStream); await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { lblMsg.Text += "服務端收到了來自: " + args.Socket.Information.RemoteHostName.RawName + ":" + args.Socket.Information.RemotePort + " 的 socket 串連"; lblMsg.Text += Environment.NewLine; }); try { while (true) { // 自訂協議(header|body):前4個位元組代表實際資料的長度,之後的實際資料為一個字串資料 // 讀取 header uint sizeFieldCount = await reader.LoadAsync(sizeof(uint)); if (sizeFieldCount != sizeof(uint)) { // 在擷取到合法資料之前,socket 關閉了 return; } // 讀取 body uint stringLength = reader.ReadUInt32(); uint actualStringLength = await reader.LoadAsync(stringLength); if (stringLength != actualStringLength) { // 在擷取到合法資料之前,socket 關閉了 return; } await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { // 顯示用戶端發送過來的資料 lblMsg.Text += "接收到資料: " + reader.ReadString(actualStringLength); lblMsg.Text += Environment.NewLine; }); } } catch (Exception ex) { var ignore = this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { SocketErrorStatus errStatus = SocketError.GetStatus(ex.HResult); lblMsg.Text += "errStatus: " + errStatus.ToString(); lblMsg.Text += Environment.NewLine; lblMsg.Text += ex.ToString(); lblMsg.Text += Environment.NewLine; }); } } // 建立一個用戶端 socket,並串連到服務端 socket private async void btnConnectListener_Click(object sender, RoutedEventArgs e) { HostName hostName; try { hostName = new HostName("127.0.0.1"); } catch (Exception ex) { lblMsg.Text += ex.ToString(); lblMsg.Text += Environment.NewLine; return; } // 執行個體化一個用戶端 socket 對象 _client = new StreamSocket(); try { // 串連到指定的服務端 socket await _client.ConnectAsync(hostName, "2211"); lblMsg.Text += "已經串連上了 127.0.0.1:2211"; lblMsg.Text += Environment.NewLine; } catch (Exception ex) { SocketErrorStatus errStatus = SocketError.GetStatus(ex.HResult); lblMsg.Text += "errStatus: " + errStatus.ToString(); lblMsg.Text += Environment.NewLine; lblMsg.Text += ex.ToString(); lblMsg.Text += Environment.NewLine; } } // 從用戶端 socket 發送一個字串資料到服務端 socket private async void btnSendData_Click(object sender, RoutedEventArgs e) { // 執行個體化一個 DataWriter,用於發送資料 if (_writer == null) _writer = new DataWriter(_client.OutputStream); // 自訂協議(header|body):前4個位元組代表實際資料的長度,之後的實際資料為一個字串資料 string data = "hello webabcd " + DateTime.Now.ToString("hh:mm:ss"); _writer.WriteUInt32(_writer.MeasureString(data)); // 寫 header 資料 _writer.WriteString(data); // 寫 body 資料 try { // 發送資料 await _writer.StoreAsync(); lblMsg.Text += "資料已發送: " + data; lblMsg.Text += Environment.NewLine; } catch (Exception ex) { SocketErrorStatus errStatus = SocketError.GetStatus(ex.HResult); lblMsg.Text += "errStatus: " + errStatus.ToString(); lblMsg.Text += Environment.NewLine; lblMsg.Text += ex.ToString(); lblMsg.Text += Environment.NewLine; } } // 關閉用戶端 socket 和服務端 socket private void btnCloseSocket_Click(object sender, RoutedEventArgs e) { try { _writer.DetachStream(); // 分離 DataWriter 與 Stream 的關聯 _writer.Dispose(); _client.Dispose(); _listener.Dispose(); lblMsg.Text += "服務端 socket 和用戶端 socket 都關閉了"; lblMsg.Text += Environment.NewLine; } catch (Exception ex) { lblMsg.Text += ex.ToString(); lblMsg.Text += Environment.NewLine; } } }}