樱花草WWW日本在线观看,色婷婷精品大在线视频,久久婷婷五月综合色国产香蕉,老牛精品亚洲成AV人片

  • HOLOLENS的SOCKET網(wǎng)絡(luò )通訊1

    2019/5/23??????點(diǎn)擊:
    多數開(kāi)發(fā)者開(kāi)發(fā)Hololens的通信功能是先想到的是system.net.socket庫里的socket,發(fā)布UWP的時(shí)候就可能出問(wèn)題,因為UWP對system庫不是完全的支持,很多方法或者類(lèi)是沒(méi)有定義的(這是一個(gè)很常見(jiàn)的發(fā)布UWP的報錯)。本文用的system.net.socket里的SAEA系列,全稱(chēng):SocketAsyncEvnetArgs,這是微軟針對高并發(fā)而設計的一套API, SAEA是異步的socket參數,使用SAEA時(shí)需要注意三點(diǎn):1.緩沖區  2.IP  3.完成后的回調,這三點(diǎn)是必要的,其次還有其他的SAEA參數,不是必要的,例如UserToken等,詳細可查API。
    using UnityEngine;
    using System.Net;
    using System.Net.Sockets;
    using System;
    using System.Text;
    //這個(gè)腳本是hololens端的SocketUDP腳本,提供發(fā)送方法,初始化并開(kāi)啟接收方法
    public class MyUdpClient : MonoBehaviour
    {
        Socket socket; //目標socket
        //發(fā)送端口
        EndPoint serverEnd; 
        IPEndPoint ipEnd; 
        //接收端口
        IPEndPoint IPLocalPoint;
        //發(fā)送用的socket異步參數
        SocketAsyncEventArgs socketAsyceArgs;
        //接收用的socket異步參數
        SocketAsyncEventArgs reciveArgs;
        //接收SAEA用來(lái)接收的緩沖區
        byte[] reciveArgsBuffer;        
        //初始化
        void InitSocket()
        {
            //定義連接的服務(wù)器ip和端口,可以是本機ip,局域網(wǎng),互聯(lián)網(wǎng)
            ipEnd = new IPEndPoint(IPAddress.Parse("10.100.172.226"), 8001);
            //初始化要接收的IP,IPAddress.Any表示接收所有IP地址發(fā)來(lái)的字節流
            IPLocalPoint = new IPEndPoint(IPAddress.Any, 8002);
            //初始化socket
            socket = new Socket(IPLocalPoint.AddressFamily, SocketType.Dgram, ProtocolType.Udp);  
            //定義服務(wù)端
            IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
            serverEnd = (EndPoint)sender;
            //初始化發(fā)送用的SAEA
            socketAsyceArgs = new SocketAsyncEventArgs();
            //設置發(fā)送用的SAEA的IP
            socketAsyceArgs.RemoteEndPoint = ipEnd;
            //初始化接收用的SAEA的緩沖區,此處我設為10K
            reciveArgsBuffer = new byte[1024 * 10];
            //初始化接收SAEA
            reciveArgs = new SocketAsyncEventArgs();
            //設置接收SAEA的接收IP地址
            reciveArgs.RemoteEndPoint = IPLocalPoint;
            //因為SAEA系列API 是異步方法,所以設置好完成方法后的回調
            reciveArgs.Completed += new EventHandler(CompletedRecive);
            //設置接收緩沖區
            reciveArgs.SetBuffer(reciveArgsBuffer, 0, reciveArgsBuffer.Length);
        }
        //異步方法完成后的complete時(shí)間
        private void CompletedRecive(object sender, SocketAsyncEventArgs e)
        {
            //通過(guò)SAEA.LastOperation這個(gè)枚舉來(lái)判斷完成的是什么方法,對應不同的操作
            switch (reciveArgs.LastOperation)
            {
                //因為reciveArgs是我專(zhuān)門(mén)用來(lái)接收的SAEA,所以這里只設置一個(gè)完成接收后用的方法
                case SocketAsyncOperation.ReceiveFrom:
                    PocessReceiveFrom(e);
                    break;       
            }
        }
        //中轉緩沖區,將數據拷貝出來(lái)給主線(xiàn)程用
        byte[] tempBytes;
        //用來(lái)通知主線(xiàn)程的參數
        bool isOk=false;
        //注意:處理這個(gè)方法是輔線(xiàn)程,不要用Unity的類(lèi),否則報錯,將收到的字節流拷貝出來(lái),通知主線(xiàn)程來(lái)處理
        //接收完成后對應的處理方法
        public void PocessReceiveFrom(SocketAsyncEventArgs e)
        {
            if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success)
            {
                //這里會(huì )造成內存垃圾以及內存碎片化,如果頻繁的長(cháng)時(shí)間的接收,建議做一個(gè)Byte池。
                tempBytes = new byte[e.BytesTransferred];     //將數據拷貝出來(lái)保證可以復用
                Array.Copy(e.Buffer, e.Offset, tempBytes, 0, tempBytes.Length);
                //通知主線(xiàn)程
                isOk = true;
            }
        }
        ////// 異步發(fā)送消息方法
        //////public void AsyncSend(byte[] bytes)
        {
            //設置緩沖區,緩沖區里是發(fā)送的字節流
            socketAsyceArgs.SetBuffer(bytes, 0, bytes.Length);
            //Debug.Log("socket異步參數字節流長(cháng)度 " + socketAsyceArgs.Buffer.Length);
            bool bo = socket.SendToAsync(socketAsyceArgs);
            if (!bo)
            {
                //在hololens上發(fā)現過(guò)一段時(shí)間scoket就不會(huì )發(fā)送數據,*后這樣處理:判斷SentToAsync方法失敗后,就重新new一個(gè)SAEA,解決socket發(fā)送失敗的問(wèn)題
                //注意初始化一個(gè)SAEA時(shí),1.IP    2.緩沖區,3.完成后的回調事件  這三個(gè)都是必要的,
                socketAsyceArgs = new SocketAsyncEventArgs();
                socketAsyceArgs.RemoteEndPoint = ipEnd;
            }
        }
        //初始化socket并測試一下
        private void Start()
        {
            InitSocket();
            TestSocekt();
        }
        //用來(lái)測試socket的方法,發(fā)送一個(gè)信息
        void TestSocekt() {
            int tempInt = 9999;
            byte[] tempBytes;
     
            tempBytes=BitConverter.GetBytes(tempInt);
            AsyncSend(tempBytes);
        }
        private void Update()
        {
            if (isOk)
            {
                //對tempBytes進(jìn)行處理
                int temp= BitConverter.ToInt32(tempBytes, 0);
                Debug.Log("接收socket,接收到了字節流,接收到的數字為 " + temp);
                isOk = false;
            }
        }
        //每隔一段時(shí)間就接受一下
        private void FixedUpdate()
        {
            socket.ReceiveFromAsync(reciveArgs);
        }
    }
    上面的代碼把接收模塊和發(fā)送模塊寫(xiě)在一起,SAEA系列是異步的,所以使用起來(lái)對于多線(xiàn)程需要一些了解。
    一般的socket需求用上面的代碼足夠用的,由于上文中只有一個(gè)接收SAEA和一個(gè)發(fā)送SAEA,所以當一個(gè)SAEA在工作時(shí),不要再讓這個(gè)SAEA工作。

    捷徑:后來(lái)發(fā)現在MixedRealTooklit里面有scoket組件,可以直接使用MRTK中Sharing文件夾中的組件,或者查看MRTK的源碼,里面是用Windows.Networking和Task寫(xiě)的Socket,找了很長(cháng)時(shí)間的SocketAPI,原來(lái)遠在天邊近在眼前,感嘆當時(shí)怎么不好好看看MRTK??!

    99久久精品国产一区二区| 国产成人无码久久久精品一| 久久精美日产AA二线三线| 伊人久久精品亚洲午夜| 亚洲热妇无码AV在线播放| 国产自偷亚洲精品页65页|