这是一个问题,主要是由于我对Winsock,套接字,UDP和一般的编程经验不足。与该问题相关的问题/答案很多,但由于对Winsock等的理解不足,我无法对其进行筛选,以了解如何解决我的问题。
问题。 我目前通过C ++应用程序和在Unity应用程序中运行的C#脚本正确地(连续)运行UDP连接。当前,C ++应用程序将来自外部触觉设备的位置数据信息转换为简单的字符串,然后通过UDP将数据报发送到unity应用程序。然后,Unity脚本将简单字符串转换回相关信息,并用于控制Unity游戏空间内的对象。这可以正常工作,但是主要是因为我已经能够在线找到脚本,只需要进行少量编辑和调整即可针对我的特定应用程序工作。我现在需要做的是将数据报从Unity应用程序发送到C ++应用程序(与我目前正在执行的操作相反),以便当游戏对象与Unity游戏空间中的对撞机进行交互时向触觉设备提供触觉反馈。当与对撞机建立联系时,我有想要发送的数据(当前通过Debug.Log打印),但是我不知道如何正确使用winsock Sentto和Recvfrom函数来使C ++应用程序主动监听(不只是发送),而且Unity应用程序正在主动发送(不只是侦听)。
我将继续浏览已经发布的问题/解决方案,看看是否可以解决,但与此同时,如果有人可以提供一些帮助,我将不胜感激。我正在使用的代码的相关部分发布在下面:
此脚本已附加到Unity中我的游戏对象上
using UnityEngine;
using System.Collections;
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Globalization;
using UnityEngine.Serialization;
public class TestUDPConnection : MonoBehaviour
{
private const int listenPort = 11000;
private UdpClient listener;
private IPEndPoint remoteIpEndPoint;
public static string currentUDPData;
private Thread listenerThread;
public bool inputSignal = false;
//bool to fix unity crash
public int fixMe = 1;
// Use this for initialization
void Start ()
{
// Creat a new thread for receiving UDP messages
listenerThread = new Thread(new ThreadStart(UDPReceive));
listenerThread.Name = "UDP Receiving Thread";
listenerThread.IsBackground = true; // run thread in background
listenerThread.Start();
}
// Thread for receiving UDP input
public void UDPReceive()
{
Debug.Log("Start receiving UDP.");
listener = new UdpClient(listenPort); // Initializes and BINDS directly (this is an overload of the UdpClient function, or to be precise the Constructor)
while (fixMe > 0) {
try {
// Opening udpclient listener on port
Debug.Log("Listening to port: " + listenPort);
// Receive bytes
remoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0); // Initializes the Endpoint with the correct Port and any IP address (UDP is connectionless the receiver doesn't need any IP address)
byte[] receiveBytes = listener.Receive(ref remoteIpEndPoint);
// Encode bytes to string (with UTF8 or ASCII Encoding)
currentUDPData = Encoding.ASCII.GetString(receiveBytes);
try {
//code is parsed here
} catch (Exception parseError) {
Debug.Log("Parsing didn't work: " + parseError.ToString());
}
} catch (Exception e) {
Debug.Log("Something went wrong: " + e.ToString());
}
}
Debug.Log("Stop receiving UDP.");
}
// Update is called once per frame
void Update ()
{
// Executed when BACKSPACE key hit
if (Input.GetKeyDown("backspace")) {
DestroyObject(gameObject);
fixMe = 0;
}
}
// Executed when object gets destroyed
void OnDisable()
{
if (listenerThread != null) {
listenerThread.Abort();
}
listener.Close();
Debug.Log("UDP receiver closed");
fixMe = 0;
}
}
这是我在C ++应用程序中拥有的脚本(脚本中有更多与触觉设备有关的代码,但这部分与UDP通信有关)
#ifndef UNICODE
#define UNICODE
#endif
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <Ws2tcpip.h>
#include <stdio.h>
#include <vector>
// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")
int iResult;
WSADATA wsaData;
SOCKET SendSocket = INVALID_SOCKET;
sockaddr_in RecvAddr;
unsigned short Port = 11000; //port communicated through
char SendBuf[1024]; //message variable
int BufLen = 1024; //max length of buffer
int main()
{
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR) {
wprintf(L"WSAStartup failed with error: %d\n", iResult);
//return 1;
}
//---------------------------------------------
// Create a socket for sending data
SendSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (SendSocket == INVALID_SOCKET) {
wprintf(L"socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
//return 1;
}
//---------------------------------------------
// Set up the RecvAddr structure with the IP address of
// the receiver (in this example case "192.168.1.1")
// and the specified port number.
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_port = htons(Port);
RecvAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
//InetPton(AF_INET, _T("127.0.0.1"), &RecvAddr.sin_addr.s_addr);
//---------------------------------------------
// Clean up and quit.
//wprintf(L"Exiting.\n");
//WSACleanup();
//return 0;
//the udp communication, data parsing, etc., is contained within this loop:
// main haptic simulation loop
while (simulationRunning)
{
//script here for various stuff...
//taking in position values of haptic device in different variables
//converting them to strings
//adding them to the pBuffer that is sent through the UDP pipeline via:
iResult = sendto(SendSocket,
pBuffer, nStrSize + 1, 0, (SOCKADDR *)& RecvAddr, sizeof(RecvAddr));
if (iResult == SOCKET_ERROR) {
wprintf(L"sendto failed with error: %d\n", WSAGetLastError());
closesocket(SendSocket);
WSACleanup();
//return 1;
}
}
因此,基本上,我想实现每个代码中发生的事情的相反过程(即,在C#Unity脚本中发送数据并在C ++应用程序脚本中接收数据)。根据我的阅读,您可以在同一套接字上发送/接收,因此似乎很容易在我的C ++仿真循环中添加几行,其中包括recvfrom函数,以及我的c ++循环的一些简单复制和粘贴。进入C#脚本(只需进行少量调整)即可获取发送的数据。我将阅读更多内容,并尝试使用不同的代码以使其同时起作用。提前感谢您提供的任何帮助!