中文字幕无码a片久久,亚洲日韩在线观看浪潮,人人超人人超碰超国产二区,国产人妻久久一区二区,国产人妻久久一区二区

福感科技有限公司 歡迎您!
聯(lián)系方式

    地址:北京市平谷區(qū)馬坊鎮(zhèn)金河北街17號(hào)院3號(hào)樓7層712

    電話:010-89968230

    網(wǎng)站:http://0743119.com

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

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


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

聲明:文章內(nèi)容整理來(lái)源于網(wǎng)絡(luò),版權(quán)屬于原作者,如有問(wèn)題,請(qǐng)聯(lián)系我們!

Copyright 2019 0743119.com

福感科技有限公司 版權(quán)所有 All Rights Reserved

京ICP備20002031號(hào)

010-89968230