winRT 网络通讯的一些问题
开发winRT工程已经一周左右,框架已经搭建完成,但是发现网络通讯这块相比Windows Phone确实有较大变化,今天总结一下遇到的问题,普通的网络连接发送接收是没什么问题的,看看官方例子就可以解决,但是由于金融交易的功能必须采用SSL证书的安全网络通讯形式,所以关于SSL这块确实纠结了几天时间。
1,创建网络连接
/// <summary> /// 创建连接 /// </summary> /// <param name="address"></param> /// <returns></returns> public async Task<NetworkStatusEnum> Connect(NetworkAddr address) { NetWorkState = NetworkStatusEnum.NotConnected; try { //创建连接 await mSocket.ConnectAsync(new HostName(address.IP), address.NetPort.ToString()); //连接成功 NetWorkState = NetworkStatusEnum.Connected; BeginReceived(); } catch(Exception ex) { NetWorkState = NetworkStatusEnum.ConnectedError; Debug.WriteLine("创建连接失败!=="+ex.Message); } return NetWorkState; }
创建连接为异步可等待方法,上层调用的时候一定要记得await,否则可能会遇到,连接没连上已经发送数据的情况。
2,连接的状态
由于StreamSocket没有连接状态属性,我们只能自定义一个枚举类型
/// <summary> /// 网络状态枚举 /// </summary> public enum NetworkStatusEnum { /// <summary> /// 已连接 /// </summary> Connected, /// <summary> /// 未连接 /// </summary> NotConnected, /// <summary> /// 连接失败 /// </summary> ConnectedError, /// <summary> /// 无网络可用 /// </summary> NetworkNotAvailable, /// <summary> /// 发送错误 /// </summary> SendError, /// <summary> /// 接收错误 /// </summary> ReceivedError }
在创建链接的时候可能会失败,这是一种常见情况,还有一种是在网络已经连接上,中间使用过程中服务器无法连接的情况就比较特殊,我们这里采用的是心跳包的方案。 客户端每10秒钟发个心跳包,服务端会反馈心跳包,保证链接通畅。
3,发送数据包
/// <summary> /// 发送数据 /// </summary> /// <param name="data"></param> /// <returns></returns> public async Task<NetworkStatusEnum> Send(byte[] data) { if (null != mSocket) { if (mWriter == null) { mWriter = new DataWriter(mSocket.OutputStream); } //把数据写入到发送流 mWriter.WriteBytes(data); //异步发送 try { await mWriter.StoreAsync(); NetWorkState = NetworkStatusEnum.Connected; } catch (Exception ex) { NetWorkState = NetworkStatusEnum.SendError; Debug.WriteLine("发送数据失败!==" + ex.Message); } return NetWorkState; } return NetWorkState; }
4,接受数据包
/// <summary> /// 数据接受 /// </summary> public async Task BeginReceived() { //绑定已连接的StreamSocket到DataReader mReader = new DataReader(mSocket.InputStream); mReader.InputStreamOptions = InputStreamOptions.Partial; while (isRun) { try { uint sizeFieldCount = await mReader.LoadAsync(16); if (sizeFieldCount == 0) { continue; } byte[] tempByteArr = new byte[sizeFieldCount]; //将刚才reader读取到的数据填充到tempByteArr mReader.ReadBytes(tempByteArr); NetWorkState = NetworkStatusEnum.Connected; PostPacket(tempByteArr); } catch(Exception ex) { NetWorkState = NetworkStatusEnum.ReceivedError; Debug.WriteLine("接受数据失败!==" + ex.Message); break; } } }
接收的时候要注意一个设置,InputStreamOptions得设置为Partial,这样就可以不用等待服务端攒到一定字节再返回,否则会影响返回的即时性。
5,SSL证书连接
由于微软取消了本地证书的X.509的帮助类,所以没法解析此证书文件,现在可以使用三方的开源类库(bouncycastle)解析它,他支持SSL安全证书网络流。方便好用,关键是开源。
http://www.bouncycastle.org/csharp/