使用System.Net.Sockets将Unity连接到C ++ WinSocket

时间:2017-03-22 20:18:01

标签: c# sockets unity3d uwp hololens

Windows 10,Unity 5.5.2 - 请注意,这会将.Net隐式限制为版本3.5。

我有一个C ++应用程序,我正试图通过无线方式连接到Unity应用程序。我希望不断地将字节数组从C ++发送到Unity。问题是,对于我希望部署到的设备(Hololens,在我的情况下),System.Net.Sockets不可用。

在C ++中,我使用Winsock2.h头实例化一个套接字。我可以使用UDP或TCP,对我的应用程序来说无关紧要。

在Unity中,我希望使用Unity.Networking或UWP来建立连接。

要使用UWP,我只看到使用async关键字的示例,这在Unity中使用是一件令人头疼的问题(我老实说不确定是否可能)。

同时,Unity.Networking似乎使用自己的协议,我不知道如何将它与我的C ++应用程序连接。

任何人都可以提供一种在Unity中完成此任务的非常简单,简洁的方法吗?

编辑:在Hololens上使用线程也很困难,异步任务似乎也是一个困难的命题。

3 个答案:

答案 0 :(得分:2)

我们使用线程和https://github.com/nickgravelyn/UnityToolbag/tree/master/Dispatcher为Unity UDP客户端构建了一个C ++,使其“线程安全”。

根据https://forums.hololens.com/discussion/578/hololens-udp-server,你可以使用 Windows.Networking.Sockets

答案 1 :(得分:2)

经过多次反复试验,我终于完成了一半的工作。如果有人可以在这个答案中填写空白(见下文),我很乐意将接受改为答案。

简而言之,我确实只使用了UWP TCP套接字。构建是一种痛苦,它在模拟器上不起作用。切换到硬件而不是模拟器使事情有效。

使用UWP for Hololens的必要TCP C#监听器:

#define uwp
//#define uwp_build

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using System.Text;
using System;
using System.Threading;
using System.Linq;



#if uwp
#if !uwp_build
using Windows.Networking;
using Windows.Networking.Sockets;
using UnityEngine.Networking;
using Windows.Foundation;
#endif
#else
using System.Net;
using System.Net.Sockets;
#endif

public class Renderer : MonoBehavior {

byte[] bytes = new byte[8192];
bool ready = false;
const int localPort = 11000;

static bool clientConnected;

#if !uwp

    TcpListener listener;
    private Socket client = null;

#else
#if !uwp_build

    StreamSocketListener socketListener;
    StreamSocket socket;
#endif
#endif

#if !uwp_build
    async
#endif
    void Start()
    {
        clientConnected = false;

#if !uwp
        IPAddress localAddr = IPAddress.Parse("127.0.0.1");
        listener = new TcpListener(localAddr, localPort);
        listener.Start();
        Debug.Log("Started!");

#else
#if !uwp_build
        socketListener = new StreamSocketListener();


        socketListener.ConnectionReceived += OnConnection;

        await socketListener.BindServiceNameAsync("11000");

}
#endif
#endif

void Update()
    {
#if !uwp
        if (listener.Pending())
        {
            client = listener.AcceptSocket();
            clientConnected = true;
        }
#endif
        // An incoming connection needs to be processed.  
        //don't do anything if the client isn't connected
        if (clientConnected)
        {



            int bytesRec = 0;
#if !uwp
            bytesRec = client.Receive(bytes);
#else
#if !uwp_build
            Stream streamIn = socket.InputStream.AsStreamForRead();

            bytesRec = streamIn.Read(bytes, 0, 8192);
            Debug.Log(bytesRec);
#endif


#endif
            byte[] relevant_bytes = bytes.Take(bytesRec).ToArray();

            //do something with these relevant_bytes

    }
#if uwp
#if !uwp_build
    private async void OnConnection(
        StreamSocketListener sender,
        StreamSocketListenerConnectionReceivedEventArgs args)
    {
        String statusMsg = "Received connection on port: " + args.Socket.Information.LocalPort;
        Debug.Log(statusMsg);
        this.socket = args.Socket;
        clientConnected = true;
    }
#endif
#endif

}

我必须在启用uwp_build的情况下从统一构建,然后在禁用它的情况下部署到Hololens - 我不知道为什么。

无论如何,这在设备本身上非常有效。它在模拟器上不起作用。当Creators 10在一周左右发布时,模拟器似乎被弃用了,这可能是一个没有实际意义的点 - 也许它可以在新的模拟器上运行。由于我正在从非UWP到UWP进行通信,因此我认为在本地计算机上运行时环回应该不是问题 - 特别是因为模拟器的IP地址与主机设备不同。如果有人知道为什么这可以在设备上工作但不能在模拟器上工作,如果有更方便的构建标志序列,我将非常感谢知道。

答案 2 :(得分:1)

此类任务有Transport Layer API。这是其样本中的代码:

// Initializing the Transport Layer with no arguments (default settings)
NetworkTransport.Init();

// An example of initializing the Transport Layer with custom settings
GlobalConfig gConfig = new GlobalConfig();
gConfig.MaxPacketSize = 500;
NetworkTransport.Init(gConfig);

ConnectionConfig config = new ConnectionConfig();
// use QosType.Reliable if you need TCP
int myReiliableChannelId  = config.AddChannel(QosType.Reliable);
// use QosType.Unreliable if you need UDP
int myUnreliableChannelId = config.AddChannel(QosType.Unreliable);

HostTopology topology = new HostTopology(config, 10);
// set listen port 8888
int hostId = NetworkTransport.AddHost(topology, 8888);

数据接收功能:

void Update()
{
    int recHostId; 
    int connectionId; 
    int channelId; 
    byte[] recBuffer = new byte[1024]; 
    int bufferSize = 1024;
    int dataSize;
    byte error;
    NetworkEventType recData = NetworkTransport.Receive(out recHostId, out connectionId, out channelId, recBuffer, bufferSize, out dataSize, out error);
    switch (recData)
    {
        case NetworkEventType.Nothing:         //1
            break;
        case NetworkEventType.ConnectEvent:    //2
            break;
        case NetworkEventType.DataEvent:       //3
            break;
        case NetworkEventType.DisconnectEvent: //4
            break;
    }
}

对于C / C ++部分,请使用标准网络套接字。例如,您可以查看Beginner's Socket Programming in C