c# - 如何广播HTTP请求?

标签 c# http mono broadcast

我正在设计一个带有传感器节点的数据采集系统,该系统使用 HTTP 在 Mono/C# 中与服务器进行通信。我使用基本的 HttpWebRequest 和 HttpListener 来实现通信。

服务器将有一个带有搜索按钮的应用程序,用于查找和显示 LAN 中存在的节点。基本上,节点将监听在特定端口上接收到的特定 Hello 消息(HTTP 请求),并在收到消息时使用其 ID 进行响应。

我的问题是:如何将HTTP请求广播到网络中的所有节点?或者,如何获取 LAN 中连接的所有计算机的 IP 地址,以便向每台计算机发送请求?

如果有更简单的方法来实现这一点,我愿意接受新的建议。谢谢你!

最佳答案

正如评论中所说,HTTP 不能这样广播。

枚举 IP 范围内的所有 IP 地址并向每个地址发送 HTTP 请求以查看是否存在某些问题并不是一个好主意。一个不太好的想法有多少取决于 Private IP Address Range 中的哪一个和您的 DHCP 服务器给出的子网掩码

  • 最常见的配置使用 192.168..* 范围和 255.255.255.0 掩码(也称为 192.168.0.0/24),并且仅提供 255 个地址。
  • 如果您的 LAN 使用 192.168..* 范围(掩码为 255.255.0.0),此代码将为您提供 65,535 个 IP 地址,供您向其发送 HTTP 请求,
  • 如果您的 LAN 使用 172...* 地址,您将获得 1'048'575 个 IP 地址,并且
  • 如果您的 LAN 使用 10...* 地址范围,您将有 16'777'215 个地址可供搜索,令人印象深刻。

您可能需要搜索大量 IP 地址。

如果您的 IP 范围不是 192.168.0.0/24,那么您也无法同时探测所有这些范围。即使您不介意生成 65,000 个线程,您的计算机也没有足够的 TCP 端口可用于响应(取决于操作系统,您可能会得到 30,000 个),因此您必须通过分批进行。

此外,如果您的网络稍微复杂一点,使用 vLAN 或路由器来分隔网络的不同区域,那么您的机器将无法自行枚举这些区域使用的范围。此时,您可能会找到一种方法来查询路由器或 ActiveDirectory,以查找网段之外的 IP 范围或主机。

总而言之,这不是一个好主意。

UDP 可能更好

更好的方法是使用(正如其他人建议的那样)UDP 广播。每个传感器节点都会监听特定的 UDP 端口,并且您的服务器将向子网的广播 IP 地址发送一条 UDP 消息。每个节点都会收到该消息,然后该节点上的代码会将某种形式的响应发送回 UDP 广播源(服务器)。然后,服务器将接收来自每个节点的 UDP 响应,其中包含每个节点的 IP 地址。

在代码级别,您创建一个套接字,使用选定的端口号将其配置为 UDP,然后您的服务器开始使用您选择的范例(同步、开始/结束、异步/等待)在该端口上接收数据。当数据到达端口时,您的回调函数将被触发,并向其传递接收到的数据以及发送该数据的服务的 IPEndPoint。

网络配置中的不同路由器通常可以设置为转发您的 UDP 广播请求和关联的响应,以便通过最少的配置(无论如何您都不需要做更多的事情来让 HTTP 请求正常工作)在您的网段之外搜索。

C# 中的简单 UDP 服务器示例可以在 here 中找到。 .

查找子网

无论您选择哪种方式,都可以使用以下代码来获取所有子网及其广播地址或完整的 IP 地址集。它将找到您计算机上所有适配器(世界上所有 gin-joint)上所有子网的所有 IP 地址。

此代码不会消除 127...* 本地地址,您可能希望这样做以避免另外 1600 万个地址进行毫无意义的搜索。

foreach ( var lSubnet in GetLocalSubnets() )
{
    var lBroadcast = lSubnet.subnetBroadastAddress;
    var lAddresses = new List<IPAddress>( lSubnet.GetAllAddresses() );
}

public static IEnumerable<IpAddressSubnet> GetLocalSubnets()
{
    foreach (NetworkInterface lAdapter in NetworkInterface.GetAllNetworkInterfaces())
    {
        foreach (UnicastIPAddressInformation lAdapterIpAddress in lAdapter.GetIPProperties().UnicastAddresses)
        {
            if (lAdapterIpAddress.Address.AddressFamily == AddressFamily.InterNetwork)
            {
                yield return new IpAddressSubnet(lAdapterIpAddress.Address, lAdapterIpAddress.IPv4Mask);
            }
        }
    }
    yield break;
}

public class IpAddressSubnet
{
    public IpAddressSubnet(IPAddress pAddress, IPAddress pSubnetMask)
    {
        address = pAddress;
        subnetMask = pSubnetMask;

        var lAddressBytes = pAddress.GetAddressBytes();
        var lSubmaskBytes = pSubnetMask.GetAddressBytes();
        var lSubmaskInverted = lSubmaskBytes.Select((b) => (byte)(b ^ 255)).ToArray();

        var lSubnetBaseAddressBytes = lAddressBytes.Zip(lSubmaskBytes, (a, m) => (byte)(a & m)).ToArray();
        subnetBaseAddress = new IPAddress(lSubnetBaseAddressBytes);
        subnetBaseAddressUint = BitConverter.ToUInt32( lSubnetBaseAddressBytes.Reverse().ToArray(), 0 );

        subnetBroadastAddress = new IPAddress(lAddressBytes.Zip(lSubmaskInverted, (a, m) => (byte)(a | m)).ToArray());
        subnetSize = BitConverter.ToUInt32( lSubmaskInverted.Reverse().ToArray(), 0 );
    }

    public IPAddress address { get; set; }
    public IPAddress subnetMask { get; set; }
    public IPAddress subnetBaseAddress { get; set; }
    uint subnetBaseAddressUint { get; set; }
    public IPAddress subnetBroadastAddress { get; set; }
    public uint subnetSize { get; set; }

    public IEnumerable<IPAddress> GetAllAddresses()
    {
        for ( uint i = 0 ; i < subnetSize - 1 ; ++ i )  // Remove 1 for the broadcast address
        {
            uint lIp = subnetBaseAddressUint + i;
            yield return new IPAddress( BitConverter.GetBytes(lIp).Reverse().ToArray() );
        }
        yield break;
    }
}

希望这有帮助

关于c# - 如何广播HTTP请求?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48510345/

相关文章:

javascript - 在 TreeView 加载后隐藏 Div 及其在更新面板中

c# - 团队 channel 1 :1 Authentication AAD integrated 上的 botframework

c# - 无法编译 monocov (Mac OS x 10.7.4)

c# - nmapi 解析 pst 文件

c# - 在 C# 中寻找可用的不可变 bool 数组

c# - 当我的 PC 通过代理连接或没有代理连接到 Internet 时,从 Gmail、live、aol 或 yahoo 帐户发送 SMTP 邮件

http - 添加 X-Request-Guid header 是什么意思

http - 如何在 Go 中禁用 http 警报

c# - 使用 HttpWebRequest 发送大文件,根据需要增加/缩小缓冲区

ios - xamarin代码的OCR阅读器?我也可以使用网络 API 请提出任何建议?