Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UDP in C# works on Windows but not Linux

I'm using mono to build a C# program that needs to send and receive using UDP. Currently my implementation works as expected on Windows but I have issues getting communication to work with my Ubuntu or Fedora systems.

Windows can broadcast and receive it's own datagrams.
Ubuntu can broadcast and receive it's own datagrams. It's broadcasts are received by Windows but it doesn't see datagrams broadcast by Windows.
Fedora can broadcast but does not receive datagrams from anywhere (not even itself). It's broadcasts are received by Windows.

When datagrams fail to reach either of the linux machines, the 'receive' function is never fired.

This is what I have so far:

int _port = 4568;
var server = new UdpClient(_port);
var send_UDP = new UdpClient();

The receive method uses the asynchronous calls of the UDPClient;

private static void receive()
{
    server.BeginReceive(new AsyncCallback(receive), null);
}
private static void receive(IAsyncResult o)
{           
    try
    {
        // I'm told that port = 0 should receive from any port.
        var sender = new IPEndPoint(IPAddress.Any, 0);
        var data = server.EndReceive(o, ref sender);
        receive();
        var str = new string(Encoding.ASCII.GetChars(data));
        postmessage(sender.Address.ToString() + ":" + sender.Port.ToString() + " > " + str);
    }
    catch {}
}

And the send method;

public static void send(string message)
{
    var target = new IPEndPoint(IPAddress.Parse("255.255.255.255"), _port);
    byte[] data = Encoding.ASCII.GetBytes(message);
    send_UDP.Send(data, data.Length, target);
}

After some testing with Fedora, it seems to be an issue with the use of 255.255.255.255 to broadcast. Is there some other way to do this?

like image 482
Micheal Hill Avatar asked Dec 11 '12 09:12

Micheal Hill


1 Answers

I already specified this in a comment but placing this as an answer since you may have overlooked it and no answers seem to be forthcoming.

Instead of using 255.255.255.255 for broadcast use your local IP subnet's broadcasting address (for instance 192.168.0.255 on a 192.168.0.1/24 subnet). The 255.255.255.255address will not be forwarded by a router (this is relevant if there are multiple subnets at your clients' sites) whereas a directed broadcast can be forwarded (if so configured). It used to be the case that routers would forward directed broadcasts per default but this was changed in RFC2644 so don't bet the farm on it ;).

Here's an example of calculating the directed IPV4 broadcast address per adapter:

public static void DisplayDirectedBroadcastAddresses()
{

    foreach (var iface in NetworkInterface.GetAllNetworkInterfaces()
             .Where(c => c.NetworkInterfaceType != NetworkInterfaceType.Loopback))
    {
        Console.WriteLine(iface.Description);
        foreach (var ucastInfo in iface.GetIPProperties().UnicastAddresses
                 .Where(c => !c.Address.IsIPv6LinkLocal))
        {
            Console.WriteLine("\tIP       : {0}", ucastInfo.Address);
            Console.WriteLine("\tSubnet   : {0}", ucastInfo.IPv4Mask);
            byte[] ipAdressBytes = ucastInfo.Address.GetAddressBytes();
            byte[] subnetMaskBytes = ucastInfo.IPv4Mask.GetAddressBytes();

            if (ipAdressBytes.Length != subnetMaskBytes.Length) continue;
                
            var broadcast = new byte[ipAdressBytes.Length];
            for (int i = 0; i < broadcast.Length; i++)
            {
                broadcast[i] = (byte)(ipAdressBytes[i] | ~(subnetMaskBytes[i]));
            }
            Console.WriteLine("\tBroadcast: {0}", new IPAddress(broadcast).ToString());
        }
    }
            
}
like image 167
Anthill Avatar answered Oct 25 '22 23:10

Anthill