Sending UDP messages works, receiving not - C# on Unity3d

我只是一个虾纸丫 提交于 2021-02-07 10:53:50

问题


Hello,

I am trying to set up a UDP connection in Unity3d and it has been giving me some headace the past days:

The Unity script I am running is supposed to receive and maybe in the future send UDP messages. Next to Unity I am using Wireshark to track the packets and PacketSender to generate and receive UDP messages.

The source of the messages is a PLC which sends a package every second, containing two floats (8 bytes) for testing. The PLC IP is 192.168.0.1 and it is connected directly via Ethernet to the Laptop running Unity. (no switch, no router)

My Ethernet Port has the IP 192.168.0.41, and the messages are coming in via Port 8052.

What I can see in Wireshark via :

  • Packages arriving from the PLC to Unity
  • Packages leaving from Unity to the PLC
  • The packages have the expected structure

What I can see / do in PacketSender:

  • packages arriving from the PLC (via Port 8052)
  • send messages to the PLC that are visible in Wireshark
  • by receiving the packages here it should also be safe to say that the firewall port window works.
  • I can NOT receive packages with PacketSender if I already started my Unity-receive script...

... which should be an indicator, that the Unity UDP socket is up and running, hopefully swallowing messages. If I call netstat -aon I can see the Unity UPD Process at the expected Port & IP; 0.0.0.0:8052 or 192.168.0.41:8052, depending on how it is created. Also I can see that no other process is using the same port.

But what does not work is to actually receive and use the data in my Unity script.

What works is to receive data send via the local IP 127.0.0.1 from another Unity script.

By now I have tried several ways to create a socket:

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 have tried...

  • ...to receive the messages sychronous or asychronous
  • ...to run the receive-loop in the Main thread or in a background thread
  • ...to en-/disable blocking of the client
  • ...to bind the client to an IP or leave it on IPAddress.Any
  • ...to shut down the HyperV switch I had on the Ethernet Port (still shut down)
  • ...to open the relevant ports in the firewall
  • ...to restart the laptop
  • ...about every solution I could find in any forum.

It feels like either the C# socket and the Step7 socket speak a different UDP or the C# socket is not functioning on the receiving side as expected. The package is really at the doorstep of the socket and it ignores it.


Setup specs: PLC: CPU315-2 PN/DP Laptop: Dell Latitude, i5, 8GB RAM, Win10 Enterprise, 64-bit Unity: Unity 2017.3.1f1, Only asset is PlayMaker


Current test 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();
    }
}

I am aware of the lack of comments in the code, but as you might have guessed, the code changed a lot lately.

Thank you for the help.


回答1:


So after a very frustrating journey I found a work-around that is not nice but does the job:

I wrote a python script that opens a socket, receives the external data and forwards it via the local IP to Unity. And that works.

Here is the code:

# 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")

Tools that are useful for your trouble shooting:

  • Install Wireshark! It is probably the best tool out there to track Internet traffic. Packages that are visible in Wireshark might not be visible for a normal application!
  • Use Packet Sender to generate and receive traffic. The application uses a basic approach to receive packages - If it can then your programm should be able to as well.
  • Check with netstat -aon if your socket is running.
  • For completion: Check your firewall settings.


来源:https://stackoverflow.com/questions/50560244/sending-udp-messages-works-receiving-not-c-sharp-on-unity3d

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!