C#中的UDP在Windows上可以工作,但在Linux上却不行。

10

我正在使用mono编写一个需要使用UDP发送和接收数据的C#程序。目前,我的实现在Windows上按预期工作,但是我在Ubuntu或Fedora系统中无法正常通信。

Windows可以广播和接收自己的数据报。
Ubuntu可以广播和接收自己的数据报,但是它不能看到Windows广播的数据报。
Fedora可以广播,但是无法从任何地方(甚至是自己)接收数据报,其广播可以被Windows接收。

当数据报未能到达Linux机器之一时,“接收”功能从未触发。

这是我到目前为止做到的:

int _port = 4568;
var server = new UdpClient(_port);
var send_UDP = new 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 {}
}

发送方法;

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

在使用 Fedora 进行一些测试后,似乎广播时使用 255.255.255.255 存在问题。是否有其他方法可以实现广播呢?


4
你有收到任何错误吗?你尝试过删除try-catch来查看是否有运行时错误吗?你设置了receive断点来检查是否被调用了吗? - Some programmer dude
4
你是否有任何防火墙规则限制数据包的自由传输?你是否确认过像Wireshark这样的工具,以确保数据包实际上正在被发送或接收? - PhonicUK
1
由于您没有指定,我认为您是在局域网上进行操作 - 使用本地IP子网(例如192.168.60.255而不是255.255.255.255)。 - Anthill
5
在同一台机器上广播到回环设备并没有什么帮助。你需要确保来自Windows机器的数据包实际上到达了Linux设备。可以在命令行中使用类似于“tcpdump -i eth0 -vv udp”的东西。你检查过防火墙设置了吗?许多Linux发行版的常见默认设置是不允许任何传入的UDP流量。 - Martin Baulig
1
首先,完全关闭防火墙,以查看是否开始工作并隔离问题。我怀疑这不是代码问题。 - Jonathon Reinhart
显示剩余9条评论
1个回答

2

我已经在评论中指明了这一点,但现在作为答案提供给你,因为你可能忽略了它,也没有其他答案。

不要使用 255.255.255.255 作为广播地址,而是使用本地IP子网的广播地址(例如,在192.168.0.1/24子网上使用192.168.0.255)。路由器不会转发 255.255.255.255 地址(如果客户站点有多个子网,则这很重要),而定向广播可以被转发(如果进行了配置)。过去,路由器默认情况下会转发定向广播,但这在RFC2644中已更改,因此不要把所有赌注都押在这上面 ; )。

以下是计算每个适配器的定向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());
        }
    }
            
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接