C#中的UDP适用于Windows,但不适用于Linux

时间:2021-07-31 20:19:14

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.

我正在使用mono来构建一个需要使用UDP发送和接收的C#程序。目前我的实现在Windows上按预期工作,但我有问题与我的Ubuntu或Fedora系统进行通信。

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.

Windows可以广播和接收它自己的数据报。 Ubuntu可以广播和接收它自己的数据报。它的广播是由Windows接收的,但它没有看到Windows播放的数据报。 Fedora可以广播,但不会从任何地方(甚至不是自己)接收数据报。它的广播是由Windows接收的。

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

当数据报无法到达任何一台Linux机器时,“接收”功能永远不会被触发。

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;

receive方法使用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?

在使用Fedora进行一些测试之后,使用255.255.255.255进行广播似乎是一个问题。还有其他方法吗?

1 个解决方案

#1


2  

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 ;).

而不是使用255.255.255.255进行广播,而是使用本地IP子网的广播地址(例如192.168.0.1/24子网上的192.168.0.255)。路由器不会转发255.255.255.255地址(如果客户端站点有多个子网,则相关),而可以转发定向广播(如果已配置)。曾经是路由器默认转发定向广播的情况,但这在RFC2644中已经改变,所以不要在农场上赌它;)。

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

以下是计算每个适配器的定向IPV4广播地址的示例:

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

}

#1


2  

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 ;).

而不是使用255.255.255.255进行广播,而是使用本地IP子网的广播地址(例如192.168.0.1/24子网上的192.168.0.255)。路由器不会转发255.255.255.255地址(如果客户端站点有多个子网,则相关),而可以转发定向广播(如果已配置)。曾经是路由器默认转发定向广播的情况,但这在RFC2644中已经改变,所以不要在农场上赌它;)。

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

以下是计算每个适配器的定向IPV4广播地址的示例:

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

}