You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unix环境下如何让同端口多UDP套接字均接收广播同步消息

问题:Unix环境下UDP多进程监听同一端口,实现所有进程接收消息

我希望在Unix环境下使用UDP同步不同进程,所有需要同步的进程将监听同一端口。我在macOS上尝试了以下C#代码,但未成功——目前仅有一个套接字能接收消息,似乎存在负载均衡分发机制,请问如何让所有套接字都接收到消息?

using System.Net;
using System.Net.Sockets;

async Task Listen (){
    try
    {
        IPEndPoint localpt = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 4000);

        UdpClient udpServer = new UdpClient();
        udpServer.ExclusiveAddressUse = false;
        udpServer.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
        udpServer.Client.EnableBroadcast = true;
        udpServer.Client.Bind(localpt);

        Console.WriteLine("listening");
        while (true)
        {
            var msg = await udpServer.ReceiveAsync();
            Console.WriteLine("Datagram received on UDP socket " + localpt);
        }
    }
    catch (Exception e)
    {
        Console.WriteLine(e.Message);
    }
}


void Send()
{
    byte[] SYNC_DATAGRAM = "SYNC"u8.ToArray();
    var client = new UdpClient();
    client.EnableBroadcast = true;
    client.Send(SYNC_DATAGRAM, SYNC_DATAGRAM.Length, new IPEndPoint(IPAddress.Parse("127.0.0.1"), 4000));
    
}

Listen();
Listen();

Thread.Sleep(1000);
Send();
Console.Read();

解决方案

在macOS(BSD系Unix系统)中,SO_REUSEADDR仅允许多个套接字绑定同一端口,但内核会通过负载均衡策略将UDP数据包分发给其中一个套接字,无法实现所有进程接收消息的需求。要让所有绑定同一端口的UDP套接字都收到全部数据包,必须使用SO_REUSEPORT套接字选项。

修改后的代码

将原代码中的SocketOptionName.ReuseAddress替换为SocketOptionName.ReusePort即可:

using System.Net;
using System.Net.Sockets;
using System.Threading;

async Task Listen (){
    try
    {
        IPEndPoint localpt = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 4000);

        UdpClient udpServer = new UdpClient();
        udpServer.ExclusiveAddressUse = false;
        // 替换为SO_REUSEPORT选项
        udpServer.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReusePort, true);
        udpServer.Client.EnableBroadcast = true;
        udpServer.Client.Bind(localpt);

        Console.WriteLine($"Process {Environment.ProcessId} listening on {localpt}");
        while (true)
        {
            var msg = await udpServer.ReceiveAsync();
            Console.WriteLine($"Process {Environment.ProcessId} received datagram: {System.Text.Encoding.ASCII.GetString(msg.Buffer)}");
        }
    }
    catch (Exception e)
    {
        Console.WriteLine(e.Message);
    }
}


void Send()
{
    byte[] SYNC_DATAGRAM = "SYNC"u8.ToArray();
    var client = new UdpClient();
    client.EnableBroadcast = true;
    client.Send(SYNC_DATAGRAM, SYNC_DATAGRAM.Length, new IPEndPoint(IPAddress.Parse("127.0.0.1"), 4000));
    
}

Listen();
Listen();

Thread.Sleep(1000);
Send();
Console.Read();

原理说明

SO_REUSEPORT在BSD系系统(包括macOS)中的核心行为是:允许多个独立进程(或同一进程内的多个套接字)绑定到完全相同的IP地址和端口,并且内核会将每个UDP数据包复制一份,发送给所有绑定的套接字。这正好满足你需要所有同步进程都接收同一消息的需求。

注意:所有需要接收消息的进程都必须设置SO_REUSEPORT选项,并且保持ExclusiveAddressUse = false,否则无法成功绑定同一端口。

内容的提问来源于stack exchange,提问作者Daniel Argüelles

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 15:55:32