不使用 System.Net.Sockets 将 Unity 连接到 C++ WinSocket
Connect Unity to C++ WinSocket WITHOUT System.Net.Sockets
Windows 10,Unity 5.5.2 - 请注意,这隐含地将 .Net 限制为 3.5 版。
我有一个 C++ 应用程序,我正在尝试通过无线方式连接到 Unity 应用程序。我希望不断地将字节数组从 C++ 发送到 Unity。问题是,对于我希望部署到的设备(在我的例子中是 Hololens),System.Net.Sockets 不可用。
在 C++ 中,我使用 Winsock2.h header 实例化了一个套接字。我可以使用 UDP 或 TCP,这对我的应用程序来说并不重要。
在 Unity 中,我希望使用 Unity.Networking 或 UWP 来建立连接。
要使用 UWP,我只见过使用 async 关键字的示例,这在 Unity 中使用起来很头疼(老实说,我不确定是否可行)。
与此同时,Unity.Networking 似乎使用了自己的协议,我不确定如何将其与我的 C++ 应用程序连接。
谁能提供一种在 Unity 中完成此任务的非常简单、简洁的方法?
编辑:在 Hololens 上使用线程也很困难,异步任务似乎也是一个困难的命题。
此类任务有一个 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
我们已经使用 Threads 和 https://github.com/nickgravelyn/UnityToolbag/tree/master/Dispatcher 构建了一个 C++ 到 Unity UDP 客户端,使其成为 'Thread safe'。
根据 https://forums.hololens.com/discussion/578/hololens-udp-server 你可以使用 Windows.Networking.Sockets
经过反复试验,终于搞定了一半。如果有人可以填写此答案中的空白(见下文),我将很乐意将接受更改为他们的答案。
简而言之,我最终只使用了 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 地址。如果有人知道为什么这可以在设备上运行但不能在模拟器上运行,并且如果有更方便的构建标志序列,我将不胜感激。
Windows 10,Unity 5.5.2 - 请注意,这隐含地将 .Net 限制为 3.5 版。
我有一个 C++ 应用程序,我正在尝试通过无线方式连接到 Unity 应用程序。我希望不断地将字节数组从 C++ 发送到 Unity。问题是,对于我希望部署到的设备(在我的例子中是 Hololens),System.Net.Sockets 不可用。
在 C++ 中,我使用 Winsock2.h header 实例化了一个套接字。我可以使用 UDP 或 TCP,这对我的应用程序来说并不重要。
在 Unity 中,我希望使用 Unity.Networking 或 UWP 来建立连接。
要使用 UWP,我只见过使用 async 关键字的示例,这在 Unity 中使用起来很头疼(老实说,我不确定是否可行)。
与此同时,Unity.Networking 似乎使用了自己的协议,我不确定如何将其与我的 C++ 应用程序连接。
谁能提供一种在 Unity 中完成此任务的非常简单、简洁的方法?
编辑:在 Hololens 上使用线程也很困难,异步任务似乎也是一个困难的命题。
此类任务有一个 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
我们已经使用 Threads 和 https://github.com/nickgravelyn/UnityToolbag/tree/master/Dispatcher 构建了一个 C++ 到 Unity UDP 客户端,使其成为 'Thread safe'。
根据 https://forums.hololens.com/discussion/578/hololens-udp-server 你可以使用 Windows.Networking.Sockets
经过反复试验,终于搞定了一半。如果有人可以填写此答案中的空白(见下文),我将很乐意将接受更改为他们的答案。
简而言之,我最终只使用了 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 地址。如果有人知道为什么这可以在设备上运行但不能在模拟器上运行,并且如果有更方便的构建标志序列,我将不胜感激。