runtime: UdpClient inconsistent behaviour between Windows and Linux.
Description
When binding a UdpClient to some specific IPEndPoint, it acts differently on Windows and Linux;
On Windows, the client receives both broadcast and unicast messages.
On Linux, the client only receives unicast messages.
Reproduction Steps
Create two dlls; one for a Windows machine and one for a Linux machine.
Replace the values of thisDeviceIp, otherDeviceIp and broadcastIp with ones appropriate for the devices.
Both devices should be able to communicate with one another and share broadcast IP.
static void Main(string[] args)
{
string thisDeviceIp = "10.0.0.1"; // 10.0.0.1 is a Windows host.
string otherDeviceIp = "10.0.0.2"; // 10.0.0.2 is a Linux host.
string broadcastIp = "10.0.0.255";
string interfaceName = "eno1" // Name of network interface with IP "thisDeviceIp" on the Linux host
UdpClient udpClient = new()
{
EnableBroadcast = true
};
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
// Attempt to set the socket option "SO_BINDTODEVICE" on Linux.
udpClient.Client.SetRawSocketOption(1, 25, Encoding.UTF8.GetBytes(interfaceName));
}
client.Client.Bind(new IPEndPoint(IPAddress.Parse(thisDeviceIp), 0xA000));
IPEndPoint unicastAdddress = new(IPAddress.Parse(otherDeviceIp), 0xA000);
IPEndPoint broadcastAddress = new(IPAddress.Parse(broadcastIp), 0xA000);
_ = Task.Factory.StartNew(() => Listener(udpClient));
// Sender logic
while (true)
{
ConsoleKeyInfo f = Console.ReadKey(true);
if (f.Modifiers.HasFlag(ConsoleModifiers.Control) && f.Key == ConsoleKey.C)
{
return;
}
if (f.Key == ConsoleKey.A)
{
udpClient.Send(Encoding.UTF8.GetBytes("data"), unicastAdddress);
}
else if (f.Key == ConsoleKey.B)
{
udpClient.Send(Encoding.UTF8.GetBytes("data"), broadcastAddress);
}
}
}
static void Listener(UdpClient udpClient)
{
int messages = 0;
IPEndPoint? remoteHost = null;
// Receiver logic.
while (true)
{
udpClient.Receive(ref remoteHost);
if (remoteHost != null)
{
Console.WriteLine($"Received message from {remoteHost} ({messages++})");
}
}
}
Expected behavior
Pressing A on one device should show up as Received message from {ip} on the other host (unicast).
Pressing B on one device should show up as Received message from {ip} on both hosts (broadcast).
Actual behavior
Pressing A on one device correctly displays a message in the other.
Pressing B, however, only shows messages on the Windows host.
Regression?
No response
Known Workarounds
Bind to IPAddress.Any instead of a specific IP.
Not preferable, since both computers may have multiple network adapters with different IP addresses and using IPAdress.Any seems to pick semi-randomly.
Configuration
.NET version: Microsoft.NETCore.App 6.0.13
OS:
- Windows host:
Windows 10 x64 - Linux host:
Ubuntu 22.04.1 LTS (GNU/Linux 5.19.0-32-generic x86_64)
This issue does not seem to be specific to the specified Linux version, as this has also been tested with ubuntu 18.04 and 20.04.
Other information
No response
About this issue
- Original URL
- State: closed
- Created a year ago
- Reactions: 1
- Comments: 19 (11 by maintainers)
Thanks @tmds for chiming in!
Yep, my question has been answered and we’ve found a decent alternative.