新时尚Windows8开发(40):StreamSocket的使用
来源:互联网 发布:mac eclipse自动补全 编辑:程序博客网 时间:2024/06/01 15:31
在Windows Store应用程序中使用Stram Socket与桌面客户端进行通信,一直没弄成功,总让俺觉得很震精,怎么会不成功呢。后来经过几回测试发现,原来是在DataReader那里出了问题,总算弄成了。
Stream Socket通常用于传输一些比较长的数据,如文件。但这里为了使演示变得更容易理解,我传输了一段字符。
首先,我们用WinForm做一个服务器端。界面不复杂,目的是侦听连接,收到传入的客户端连接后,向客户端发送一条字符串消息。
处理的逻辑代码如下:
using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows.Forms;using System.IO;using System.Net;using System.Net.Sockets;namespace TestServerApp{ public partial class Form1 : Form { TcpListener m_Listener = null;//用于监听链接 TcpClient m_Client = null;//传入的客户端 public Form1() { InitializeComponent(); this.btnStart.Enabled = true; this.btnStop.Enabled = false; } /// <summary> /// 向客户端发送字符串 /// </summary> private void SendMessage(TcpClient client) { using (var stream = client.GetStream()) { byte[] buffer = Encoding.UTF8.GetBytes("奔,不停地奔,奔向传说中的荒原;飞,不停地飞,飞向天空的那一端。"); uint len = (uint)buffer.Length; // 先发送长度 stream.Write(BitConverter.GetBytes(len), 0, sizeof(uint)); // 再发送数据 stream.Write(buffer, 0, buffer.Length); } } private async void btnStart_Click(object sender, EventArgs e) { if (this.m_Listener == null) { this.m_Listener = new TcpListener(IPAddress.Parse(this.txtAddr.Text), Convert.ToInt32(this.udPort.Value)); } this.m_Listener.Start(); this.lblMsg.Text = "监听已开始。"; this.btnStart.Enabled = false; this.btnStop.Enabled = true; try { m_Client = await m_Listener.AcceptTcpClientAsync(); SendMessage(m_Client); } catch (SocketException se) { this.lblMsg.Text = se.Message; } catch (Exception ex) { this.lblMsg.Text = ex.Message; } } private void btnStop_Click(object sender, EventArgs e) { if (m_Listener != null) { m_Listener.Stop(); this.lblMsg.Text = "监听已停止。"; } this.btnStart.Enabled = true; this.btnStop.Enabled = false; } }}
接着是Win8 App客户端。
因为我们要使用网络连接,在创建项目后,把开清单文件,切换到【功能】选项卡,把和网络连接有关的选项勾上。
打开主页MainPage的XAML代码编辑器(设计视图),简单布局一下界面。
<Page x:Class="WCleintApp.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:WCleintApp" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <Grid Grid.Row="0" Margin="3"> <Grid.RowDefinitions> <RowDefinition Height="auto"/> <RowDefinition Height="auto"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="auto"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <TextBlock Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" Text="服务器:"/> <TextBlock Grid.Row="1" Grid.Column="0" VerticalAlignment="Center" Text="端口:"/> <TextBox x:Name="txtServer" Grid.Row="0" Grid.Column="1" Margin="2,3"/> <TextBox x:Name="txtPort" Grid.Row="1" Grid.Column="1" Margin="2,3"/> </Grid> <StackPanel Grid.Row="1" Margin="5"> <Button Content="连接" Click="onConnClick" Margin="3,8,0,12" Padding="4,2.5"/> <TextBox x:Name="txtRec" Margin="5,7,0,0" Height="200" IsReadOnly="True"/> </StackPanel> </Grid></Page>
切换到隐藏代码视图,完成功能代码。
using System;using System.Collections.Generic;using System.IO;
........
using Windows.UI.Xaml.Navigation;using Windows.Networking;using Windows.Networking.Sockets;using Windows.Storage.Streams;namespace WCleintApp{ /// <summary> /// 可用于自身或导航至 Frame 内部的空白页。 /// </summary> public sealed partial class MainPage : Page { StreamSocket mSocket = null;//局部变量 bool isConnected; //标识是否已经进行了连接 public MainPage() { this.InitializeComponent(); this.isConnected = false; } private async void onConnClick(object sender, RoutedEventArgs e) { if (mSocket ==null) { mSocket = new StreamSocket(); } // 如果还没连接就进行连接 if (this.isConnected == false) { HostName hServer = new HostName(txtServer.Text); try { await mSocket.ConnectAsync(hServer, txtPort.Text); this.isConnected = true; } catch { this.isConnected = false; } } DataReader dr = new DataReader(mSocket.InputStream); // ByteOrder要设置为LittleEndian,不然会报错 dr.ByteOrder = ByteOrder.LittleEndian; dr.UnicodeEncoding = UnicodeEncoding.Utf8;//编码 // 先读出一个uint的值,4个字节,这样就知道要接收数据的长度 var il = await dr.LoadAsync(sizeof(uint)); // 如果不相等,说明读到的不是uint值,因为必须4个字节 if (il != sizeof(uint)) { txtRec.Text = "无法确定数据大小。"; return; } // 确定流中数据的长度 uint strlen = dr.ReadUInt32(); // 继续加载剩下的数据 await dr.LoadAsync(strlen); txtRec.Text = dr.ReadString(strlen); //必须与流分离,避免将整个流也释放 dr.DetachStream(); dr.Dispose(); } }}
先运行服务器端,输入本机IP和监听端口,然后开始监听。
再运行客户端,输入服务器的IP和端口,进行连接,如果成功,就会收到服务器端发过来的字符串。
- 新时尚Windows8开发(40):StreamSocket的使用
- 新时尚Windows8开发(23):那些关于按钮的事
- 新时尚Windows8开发(36):Play To的一些事情
- 新时尚Windows8开发(39):文件的Read和Write
- 新时尚Windows8开发(2):应用程序生命周期
- 新时尚Windows8开发(3):应用程序状态
- 新时尚Windows8开发(5):消息框
- 新时尚Windows8开发(6):资源 & 本地化
- 新时尚Windows8开发(20):FlipView控件
- 新时尚Windows8开发(21):分组视图
- 新时尚Windows8开发(25):缩放视图
- 新时尚Windows8开发(35):后台传输
- 新时尚Windows8开发(38):聊天程序
- 新时尚Windows8开发(18):制作类似单行簿的输入控件
- 新时尚Windows8开发(27):根据应用程序的视图状态调整UI
- 新时尚Windows8开发:那些关于按钮的事
- 新时尚Windows8开发(28):多媒体捕捉(低级篇)
- 新时尚Windows8开发(29):多媒体捕捉(高级篇)
- ASP在线转flv+所略图+flash在线录制视频
- Visualforce Mobile Tab Considerations
- Flex框架及最详细比较 MX and Spark组件
- mac OS X 下ft_rich游戏的重构
- 设计模式学习之Adapter模式
- 新时尚Windows8开发(40):StreamSocket的使用
- cocos2d-x游戏开发(五)神奇的自动释放
- (李嘉诚)教五年内买车买房——理财篇
- 用Ebay API下架商品的办法
- 将相帅三才怎么用
- Eclipse快捷键
- Asp.Net音频文件上传和播放
- java多线程
- Android属性之build.prop生成过程分析