I want to receive a UDP message which was broadcasted to 255.255.255.255 with a UdpClient within Unity.
But whatever combination of settings I try, it only receives a message, if it was sent from localhost.
I have tried fitted example code from these resources, non worked:
https://gist.github.com/michaelosthege/857acac92b8ee689a6bb30d5bf23d9f6
C# UDP Broadcast and receive example
UdpClient receive on broadcast address
How to do Network discovery using UDP broadcast
I'm running the Code below a task.
private void Listen()
{
udpClient = new UdpClient(9000);
//udpClient.Client.Bind(new IPEndPoint(IPAddress.Any, 9000));
//udpClient.EnableBroadcast = true;
//udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
//udpClient.ExclusiveAddressUse = false;
//broadcastAddress = new IPEndPoint(IPAddress.Any, 9000);
//udpClient.Client.Bind(broadcastAddress);
//udpClient.Connect(broadcastAddress);
//var from = new IPEndPoint(IPAddress.Any, 9000);
var from = new IPEndPoint(0, 0);
while (true)
{
var receive = udpClient.Receive(ref from);
var msg = Encoding.UTF8.GetString(receive);
Debug.Log($"Received message \"{msg}\"");
Debug.Log($"from {from} ({from.Address})");
}
}
I have used several of the commented lines in combination.
When I send something from within the same Application to 255.255.255.255 with another UdpClient on port 9000, it works as expected.
When I send something from any other machine on the network to 255.255.255.255
any machine in the network receives it (checking with PacketSender on osx devices)
On the windows machine I'm developing this application on, the message is received by UdpSenderReceiver
But the udpClient from within Unity does not receive anything - and the Firewall does not ask or tell me anything.
What could be the issue here?
Apparently Windows Defender by default blocks the Unity Editor (but not UdpSenderReceiver).
I had to resolve it by Admitting the Unity Editor on the public domain
The Rules for
Unity 2019.3.3f1 Editor
Unity 2019.3.4f1 Editor
had been present and were not modified.
I modified the Rule for Unity 2019.2.4f1 Editor in order to allow access from the public domain (I simply allowed all domains).
Related
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.
If you want to receive from external source you need to allow Unity on firewall or disable firewall. Firewall blocks unity editor connection with external source, that is why you can send data but can not receive. If you build your project, your code will work, because it will ask you on first running
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.
Our C# applications targeting .NET 4.0 sends an udp broadcast from time to time to IPAddress.Broadcast. We recently received a log (run on Win 8.1 Pro), which shows up that sending to 255.255.255.255:somePort resulted in a SocketException with ErrorCode 10065 (WSAEHOSTUNREACH).
I'd consider this as non remarkable, if either the network connection is lost or if sending to a specific machine. But at the time of the exception, the network was up and running, even incoming UDP packages could be read from the same socket.
Here's the code being used:
public void Setup(){
_incoming = new IPEndPoint(IPAddress.Any, IncomingPort);
_outgoing = new IPEndPoint(IPAddress.Broadcast, OutgoingPort);
_udpClient = new UdpClient();
_udpClient.Client.ExclusiveAddressUse = false;
_udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
_udpClient.Client.Bind(_incoming);
}
public void Send(byte[] dataToSend)
{
_udpClient.Send(dataToSend, dataToSend.Length, _outgoing);
}
Now the two questions regarding this issue:
1.) What could cause this behavior?
2.) What scenario do i need to setup to, in order to be able to test the same behavior?
I trying to write a TFTP client for a class project.
Using the UdpClient class I can successfully request data from the server but the returned packet never reaches my code.
My firewall is turned off.
I can observe the returned packet in wireshark but UdpClient.Receive blocks indefinitely.
mUdpClient is initialized like this in the constructor: mUdpClient = new UdpClient();
mUdpClient is connected like this
public void connect(String host, int port) {
mServerAddress = System.Net.Dns.GetHostAddresses(host)[0];
var endPoint = new IPEndPoint(mServerAddress, port);
mUdpClient.Connect(endPoint);
}
After the connect I send my request which is successful (as observed in wireshark)
This is what my receive code looks like
private void receiveResponse() {
var newEndpoint = new IPEndPoint(IPAddress.Any, 0);
byte[] response = mUdpClient.Receive(ref newEndpoint);
Console.Out.WriteLine(response);
}
This has been tested on my Surface Pro and a Windows 8.1 VirtualBox VM running under Debian.
Note that since you are using the Connect() method on your UDP socket, you will only see datagrams actually sent from that IPEndPoint. If your remote host for some reason uses a different IPEndPoint to send data back to you, you won't see it. So maybe try not using the default host feature (i.e. don't call Connect...just provide the remote IPEndPoint on each Send() call).
I'm currently developing a network application on my machine with 2 network interfaces with the following setup -
I want to send UDP message by using the first configuration with IP 192.168.1.2.
using (var udpClient = new UdpClient(5556))
{
udpClient.Connect(IPAddress.Parse("192.168.1.2"), 5556);
// DO STUFF
}
When I try this I get the following error -
No connection could be made because the target machine actively
refused it
Strange this is that when I disable my other network that this works perfectly but with 2 connections (LAN & WiFi) it doesn't work anymore...
I guess that it is sending on wrong adapter?
Is this because my Default gateway is the same or what am I doing wrong?
I'm new to developing network-based applications...
You have to specify an IPEndPoint with networking card IP like this:
var endpoint = new IPEndPoint(IPAddress.Parse("192.168.1.2"), portNum);
UdpClient client = new UdpClient(endpoint);
You are not telling UdpClient which IP to use.
UdpClient has a constructor that can take an IPEndPoint.
const string ip = "192.168.1.2";
const int port = 5556;
var listenEndpoint = new IPEndPoint(IPAddress.Parse(ip), port);
var udpClient = new UdpClient(listenEndpoint);
I'm not that good in C# but I think I understand the problem. You are binding your udpClient to port 5556 but you're not specifying the IP address. The OS will select the IP address for you. I suppose it could be either 192.168.1.2 or 192.168.1.5, you cannot tell which one.
Then with the same udpClient you are trying to connect to a remote host listening on 192.168.1.2, port 5556. And probably nobody is listening there. This is why you receive the error.
I would do the following (sorry for my bad C# skills):
Have two udpClient's, in one thread or program/process:
var udpClient1 = new UdpClient("192.168.1.2", 5556);
This one will listen on IP addres 192.168.1.2, port 5556.
in second thread or program/process:
var udpClient2 = new UdpClient(); //doesn't matter which (IP, port) the OS will bind it to.
udpClient2.Connect(IPAddress.Parse("192.168.1.2"), 5556); //connect to peer/server listening in (IP=192.168.1.2, port=5556)
You could handle both udpClient1 and udpClient2 in the same thread also.
The important is that if you connect to and (IP, port) there has to be some application/process listening there. Otherwise, the remote host will send an ICMP message indicating the datagram cannot be delivered. The connection is refused.
I'm working on a system to send data between peers on a network. One app is written in Java for the Android. The other app is written in C# on the PC.
I wrote code in Java on the Android to send UDP datagrams. And I wrote C# code to both send and receive datagrams. I tried to send messages from Android to PC. I could see the message in WireShark but not in my program. So, I put my program on a second PC. I succeeded in sending a message from my PC to the second one. But when I tried to send a message from seond PC back to mine it failed. I could see it in WireShark on my PC but not my application. Im at a loss for what to try next. Do you have any suggestions? Why would the UDP packet be visible in WireShark but not my application?
Here is my code.
//C# code on PC
//Sender
sending_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, rotocolType.Udp);
send_to_address = IPAddress.Parse(strIPAddress);
sending_end_point = new IPEndPoint(send_to_address, intPort);
sending_socket.EnableBroadcast = true;
byte[] bytMessage = Encoding.ASCII.GetBytes(strMessage);
sending_socket.SendTo(bytMessage, sending_end_point);
//Listener
UdpClient listener = new UdpClient(listenPort);
IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, listenPort);
byte[] bytReceiveDataByteArray;
try
{
listener.EnableBroadcast = true;
while (isRunning)
{
//listen for data from sender
bytReceiveDataByteArray = listener.Receive(ref groupEP);
//Fire an event to send the data to the hosting code
if (DataReceived != null)
{
DataReceivedEventArgs e = new DataReceivedEventArgs(bytReceiveDataByteArray);
DataReceived(this, e);
}
}
}
//Java code on Android
DatagramSocket socket = new DatagramSocket();
InetAddress serverIP = InetAddress.getByName(strIpAddress);
byte[] outData = (strMsg).getBytes();
DatagramPacket out = new DatagramPacket(outData,outData.length, serverIP,50005);
socket.send(out);
socket.close();
Thanks,
Mike
If I understand the problem correct when your program runs on a specific PC (lets call it "Windows1") it never receives the UDP packets. It will not receive them from Java Android or from C# code running on a different PC ( lets call it "Windows2").
However when you run your program on "Windows2" it DOES receive messages from "Windows1". Sounds like you have the firewall enabled on "Windows1" and do not have an exception for UDP port 50005. On "Windows2" your firewall is turned off or has the exception for 50005 and this is why it receives messages from "Windows1".
Note that since UDP is not connection oriented, firewall errors will not cause the usual connection timed out error. The messages are just dropped and you never get an error.