Отправка UDP-сообщений работает, не получая - C # на Unity3d - PullRequest
0 голосов
/ 28 мая 2018

Здравствуйте,

Я пытаюсь установить UDP-соединение в Unity3d, и в последние дни у меня возникают некоторые проблемы:

Предполагается, что выполняемый мной сценарий Unity получити, возможно, в будущем отправлять UDP-сообщения.Рядом с Unity я использую Wireshark для отслеживания пакетов и PacketSender для генерации и получения сообщений UDP.

Источником сообщений является ПЛК, который каждую секунду отправляет пакет, содержащий два числа с плавающей запятой(8 байт) для тестирования.IP ПЛК - 192.168.0.1, и он напрямую подключен через Ethernet к ноутбуку с Unity.(без коммутатора, без маршрутизатора)

Мой порт Ethernet имеет IP 192.168.0.41, и сообщения поступают через порт 8052.

Что я вижу в Wireshark через:

  • Пакеты, поступающие из ПЛК в Unity
  • Пакеты, отправляемые из Unity в ПЛК
  • Пакеты имеют ожидаемую структуру

Что я могусмотрите / делайте в PacketSender:

  • пакеты, поступающие из ПЛК (через порт 8052)
  • отправляют сообщения в ПЛК, которые видны в Wireshark
  • , получаяпакеты здесь также можно с уверенностью сказать, что окно порта брандмауэра работает.
  • Я НЕ МОГУ получать пакеты с PacketSender, если я уже запустил свой скрипт Unity-receive ...

... что должно быть индикатором того, что UDP-сокет Unity запущен и работает, мы надеемся проглотить сообщения.Если я позвоню netstat -aon, я смогу увидеть процесс Unity UPD на ожидаемом порту и IP;0.0.0.0:8052 или 192.168.0.41:8052, в зависимости от того, как он создан.Также я вижу, что ни один другой процесс не использует этот порт.

Но что не работает, так это фактический прием и использование данных в моем сценарии Unity.

Что работает, так это получение данных, отправляемых через локальный IP 127.0.0.1 из другого сценария Unity.

К настоящему времени я пробовал несколько способов создания сокета:

var udpClient = new UdpClient(8052,AddressFamily.InterNetwork)
var udpClient = new UdpClient(8052)
UdpClient udpClient = new UdpClient(8052,AddressFamily.InterNetwork)
var udpClient = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

Iпытался ...

  • ... получать сообщения синхронные или асинхронные
  • ... для запуска цикла приема в основном потоке или в фоновом потоке
  • ... для включения / отключения блокировки клиента
  • ... для привязки клиента к IP или оставления его на IP-адресе. Любой
  • ... для закрытиявыключите коммутатор HyperV, который был у меня на порту Ethernet (все еще выключен)
  • ..., чтобы открыть соответствующие порты в брандмауэре
  • ..., чтобы перезагрузить ноутбук
  • ... о каждом решении, которое я мог найти на любом форуме.

Такое чувство, что сокет C # и сокет Step7 говорят по-разномуUDP или C # сокет не работает на принимающей стороне, как ожидалось.Пакет действительно находится на пороге сокета и игнорирует его.


Характеристики установки: ПЛК: CPU315-2 PN / DP Портативный компьютер: Dell Latitude, i5, 8 ГБ ОЗУ, Win10 Enterprise, 64-бит Unity: Unity 2017.3.1f1, единственный актив - PlayMaker


Текущий тестовый код:

</p>

<code>using System;
using System.Net;
using System.Net.Sockets;
using UnityEngine;
using System.Threading;


public class UDPReceive03 : MonoBehaviour
{
    Thread receiveThread;
    public UdpClient socket;
    private bool canReceive;
    public static bool messageReceived;
    public String statusThread;

    public int UDP_LISTEN_PORT;

    private int alive;

    // Use this for initialization
    void Start()
    {
        UDP_LISTEN_PORT = 8052;
        print("started");
        canReceive = true;
        messageReceived = false;


        alive = 0;

        receiveThread = new Thread(new ThreadStart(ReceiveData));
        receiveThread.IsBackground = true;
        receiveThread.Start();
    }

    // Update is called once per frame
    void Update()
    {
        // I know the code below is ugly, but that was my rebellion agains the situation
        statusThread = (canReceive) ? "Waiting" : "Busy";

        if (alive % 180 == 0)
            sendResponse(1);

        alive = (alive<180) ? alive + 1 : 1;
    }

    private void ReceiveData()
    {
        using (var udpClient = new UdpClient(8052,AddressFamily.InterNetwork))
        {
            int loggingEvent = 0;
            while (true)
            {
                print("started to receive");
                IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
                var receivedResults = udpClient.Receive(ref remoteEndPoint);
                loggingEvent += receivedResults.Length;
                print("Success, received " + loggingEvent.ToString() + " bytes.");
                sendResponse(loggingEvent);
            }
        }
    }


    private void sendResponse(int count)
    {
        socket = new UdpClient(8051);
        // sending data
        IPEndPoint target = new IPEndPoint(IPAddress.Parse("192.168.0.1"), 2000);
        // send a couple of sample messages:
        for (int num = 1; num <= count; num++)
        {
            byte[] message = new byte[num];
            socket.Send(message, message.Length, target);
        }
        socket.Close();
    }
}
</code>

Мне известно об отсутствиикомментарии в коде, но, как вы уже догадались, в последнее время код сильно изменился.

Спасибо за помощь.

1 Ответ

0 голосов
/ 05 июня 2018

Итак, после очень разочаровывающего путешествия я нашел обходной путь, который нехорошо, но выполняет свою работу:

Я написал скрипт на python, который открывает сокет, получает внешние данные и передает их через локальныйIP для Unity.И это работает.

Вот код:

# Import libraies
import socket
import time

# Set send IP adress and port
UDP_IP = "127.0.0.1"
UDP_PORT_Rec = 8052
UDP_PORT_Unity = 8055

print("Receiving on Port:" + str(UDP_PORT_Rec))
print("Sending to IP:" + UDP_IP + ":" + str(UDP_PORT_Unity))

# Set socket to send udp messages and bind port
sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
sock.bind(('',UDP_PORT_Rec));

## Keep sending message from file location
while True:
    data, addr = sock.recvfrom(1024) #buffer size, hopefully no problem if too big
    print("Received")

    sock.sendto(data, (UDP_IP, UDP_PORT_Unity))
    print("Send")

Инструменты, которые полезны для устранения неполадок:

  • Установка Wireshark !Вероятно, это лучший инструмент для отслеживания интернет-трафика.Пакеты, которые видны в Wireshark, могут быть не видны для обычного приложения!
  • Используйте Packet Sender для генерации и получения трафика.Приложение использует базовый подход к приему пакетов. Если это возможно, ваша программа также сможет это сделать.
  • Проверьте с помощью netstat -aon, работает ли ваш сокет.
  • Для завершения: Проверьтенастройки вашего брандмауэра.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...