開發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/
