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

如何在ASP.NET Core中实现IP组播/广播以完成局域网服务发现

局域网内ASP.NET Core 8 Web API服务发现方案

一、优化SSDP实现解决偶尔失效问题

如果此前用RSSDP偶尔失效,可从以下维度调整:

  • 调整心跳与超时配置:将SSDP通知发送频率设为每30秒一次,延长客户端缓存服务信息的超时时间至5分钟以上,避免服务记录被过早丢弃。
  • 适配多网卡场景:遍历服务器所有可用IPv4网卡,向每个网卡对应的子网发送SSDP通知,避免因默认网卡选择错误导致部分子网无法接收消息。
  • 放行防火墙端口:在服务器和客户端开放UDP 1900端口(SSDP默认端口),同时添加UPnP相关的出入站规则。

简化版手动SSDP实现示例(ASP.NET Core后台服务):

public class SsdpBroadcastService : BackgroundService
{
    private readonly IConfiguration _config;
    private UdpClient _udpClient;
    private readonly ILogger<SsdpBroadcastService> _logger;
    private readonly string _serviceLocation;

    public SsdpBroadcastService(IConfiguration config, ILogger<SsdpBroadcastService> logger)
    {
        _config = config;
        _logger = logger;
        _serviceLocation = $"http://{GetLocalIpAddress()}:{_config["Port"]}/api/service-info";
    }

    private string GetLocalIpAddress()
    {
        return Dns.GetHostEntry(Dns.GetHostName())
            .AddressList.FirstOrDefault(ip => ip.AddressFamily == AddressFamily.InterNetwork)?.ToString() ?? "127.0.0.1";
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        _udpClient = new UdpClient();
        var multicastEndpoint = new IPEndPoint(IPAddress.Parse("239.255.255.250"), 1900);
        var ssdpMessage = $"NOTIFY * HTTP/1.1\r\n" +
                          $"HOST: 239.255.255.250:1900\r\n" +
                          $"CACHE-CONTROL: max-age=300\r\n" +
                          $"LOCATION: {_serviceLocation}\r\n" +
                          $"NT: urn:schemas-custom-org:service:WebApi:1\r\n" +
                          $"NTS: ssdp:alive\r\n\r\n";

        while (!stoppingToken.IsCancellationRequested)
        {
            try
            {
                byte[] data = Encoding.UTF8.GetBytes(ssdpMessage);
                await _udpClient.SendAsync(data, data.Length, multicastEndpoint);
                _logger.LogInformation("SSDP notification sent");
                await Task.Delay(TimeSpan.FromSeconds(30), stoppingToken);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to send SSDP notification");
                await Task.Delay(TimeSpan.FromSeconds(10), stoppingToken);
            }
        }

        _udpClient.Dispose();
    }
}

在Program.cs中注册后台服务:

builder.Services.AddHostedService<SsdpBroadcastService>();

二、基于UDP多播的自定义服务发现

这是轻量化且高效的方案,无需第三方依赖,效率远高于IP扫描:

  • 服务器端:启动后台服务,定期向局域网多播地址(如224.0.0.100)发送包含服务IP、端口、唯一标识的JSON数据包。
  • 客户端:监听同一多播地址,收到数据包后解析服务信息,维护可用服务列表。

服务器端示例代码:

public class UdpMulticastService : BackgroundService
{
    private readonly IConfiguration _config;
    private UdpClient _udpClient;
    private readonly ILogger<UdpMulticastService> _logger;

    public UdpMulticastService(IConfiguration config, ILogger<UdpMulticastService> logger)
    {
        _config = config;
        _logger = logger;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        var multicastIp = IPAddress.Parse("224.0.0.100");
        int multicastPort = 5000;

        _udpClient = new UdpClient();
        _udpClient.JoinMulticastGroup(multicastIp);

        var serviceInfo = new
        {
            ServiceId = Guid.NewGuid().ToString(),
            IpAddress = GetLocalIpAddress(),
            Port = _config["Port"],
            ServiceName = "MyBusinessWebApi",
            Timestamp = DateTime.UtcNow
        };

        while (!stoppingToken.IsCancellationRequested)
        {
            try
            {
                string json = JsonSerializer.Serialize(serviceInfo);
                byte[] data = Encoding.UTF8.GetBytes(json);
                await _udpClient.SendAsync(data, data.Length, new IPEndPoint(multicastIp, multicastPort));
                _logger.LogInformation("UDP multicast sent");
                await Task.Delay(TimeSpan.FromSeconds(20), stoppingToken);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to send UDP multicast");
                await Task.Delay(TimeSpan.FromSeconds(10), stoppingToken);
            }
        }

        _udpClient.DropMulticastGroup(multicastIp);
        _udpClient.Dispose();
    }

    private string GetLocalIpAddress()
    {
        return Dns.GetHostEntry(Dns.GetHostName())
            .AddressList.FirstOrDefault(ip => ip.AddressFamily == AddressFamily.InterNetwork)?.ToString() ?? "127.0.0.1";
    }
}

客户端监听示例(控制台程序):

using System.Net;
using System.Net.Sockets;
using System.Text.Json;

var multicastIp = IPAddress.Parse("224.0.0.100");
int multicastPort = 5000;

using var udpClient = new UdpClient(multicastPort);
udpClient.JoinMulticastGroup(multicastIp);

Console.WriteLine("Listening for Web API services...");

while (true)
{
    var result = await udpClient.ReceiveAsync();
    string json = Encoding.UTF8.GetString(result.Buffer);
    var serviceInfo = JsonSerializer.Deserialize<ServiceInfo>(json);
    
    Console.WriteLine($"Found service: {serviceInfo.ServiceName} at {serviceInfo.IpAddress}:{serviceInfo.Port}");
}

public class ServiceInfo
{
    public string ServiceId { get; set; }
    public string IpAddress { get; set; }
    public string Port { get; set; }
    public string ServiceName { get; set; }
    public DateTime Timestamp { get; set; }
}

三、使用mDNS(多播DNS)实现标准服务发现

mDNS是局域网服务发现的标准协议(RFC 6762),Windows 10+、macOS、Linux均原生支持:

  • 服务器端:在ASP.NET Core中注册mDNS服务,声明服务类型(如_http._tcp.local)和端口。
  • 客户端:通过mDNS查询获取局域网内的服务记录,解析服务地址。

可借助轻量NuGet包实现(如MdnsLite),核心逻辑:

  1. 服务器启动时,向本地mDNS注册服务,指定服务名称、类型、端口。
  2. 客户端发送mDNS查询请求,接收响应后提取服务的IP和端口信息。

各方案对比

方案优点缺点
优化SSDP符合UPnP标准,兼容性好配置复杂,易受防火墙影响
UDP多播实现简单,效率极高无标准格式,需自定义协议
mDNS标准协议,系统原生支持部分旧系统可能需额外配置

内容的提问来源于stack exchange,提问作者Luka

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 02:40:02