Как ОБА и непрерывно отправлять и получать через UDP и пост-процессинговые дейтаграммы на обоих концах (используя один и тот же сокет?) - PullRequest
1 голос
/ 17 апреля 2019

Это проблема в основном из-за моей неопытности с winsock, сокетами, UDP и программированием в целом.По этой проблеме опубликовано много вопросов / ответов, но я не смог их просмотреть из-за своего плохого понимания winsock и т. Д., Чтобы понять, как решить мою проблему.

Проблема,В настоящее время у меня есть соединение UDP, работающее (непрерывно), правильно, через приложение C ++ и скрипт C #, работающий в приложении Unity.В настоящее время приложение C ++ преобразует информацию о положении с внешнего тактильного устройства в простую строку и отправляет эту дейтаграмму через UDP в приложение Unity.Затем сценарий Unity преобразует простую строку обратно в соответствующую информацию и используется для управления объектами в игровом пространстве Unity.Это прекрасно работает, но в основном потому, что я смог найти в Интернете сценарии, которые требовали лишь небольшого редактирования и настройки для работы с моим конкретным приложением.Теперь мне нужно отправить дейтаграммы из приложения Unity в приложение C ++ (обратное тому, что я сейчас делаю) для обеспечения тактильной обратной связи с тактильными устройствами, когда игровой объект взаимодействует с коллайдерами в игровом пространстве Unity.У меня есть данные, которые я хочу отправить, доступные при установлении контакта с коллайдерами (в настоящее время печатает через Debug.Log), но я не знаю, как правильно использовать функции Ssoto и Recvfrom из winsock, чтобы приложение 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 # (с небольшими изменениями), чтобы получить отправленные данные.Я буду читать больше и пробовать другой код, чтобы узнать, как он будет работать в это время.Заранее благодарим за любую помощь, которую вы можете оказать!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...