【发布时间】:2021-06-29 14:51:06
【问题描述】:
我正在使用 C# 实现服务发现。为了解决一些问题,我实现了广播和多播,简化为所示的 sn-ps。
客户端广播:
var requestData = new byte[]{ /* Whatever */}
// Configure broadcast
var ipBroadcastEndPoint = new IPEndPoint(IPAddress.Broadcast, 12301);
var broadcastServerEp = new IPEndPoint(IPAddress.Any, 0);
var broadcastClient = new UdpClient {EnableBroadcast = true};
broadcastClient.Client.Bind(_broadcastServerEp);
// Send a request:
broadcastClient.Send(requestData, requestData.Length, ipBroadcastEndPoint);
// Listen for a reply:
var broadcastserverEp = new IPEndPoint(IPAddress.Any, 0);
var broadcastserverResponseData = broadcastClient.Receive(ref broadcastserverEp);
客户端多播:
var requestData = new byte[]{ /* Whatever */}
// Configure multicast
var ipMulticastEndPoint = new IPEndPoint(IPAddress.Parse("239.255.255.253"), 12302);
var multicastServerEp = new IPEndPoint(IPAddress.Any, 0);
var multicastClient = new UdpClient(AddressFamily.InterNetwork);
multicastClient.JoinMulticastGroup(IPAddress.Parse("239.255.255.253"), 32);
multicastClient.Client.Bind(_multicastServerEp);
// Send a request:
multicastClient.Send(requestData, requestData.Length, ipMulticastEndPoint);
// Listen for a reply:
var multicastserverEp = new IPEndPoint(IPAddress.Any, 0);
var multicastserverResponseData = multicastClient.Receive(ref multicastserverEp);
服务器端广播:
// Listen for broadcast
Task.Run(() =>
{
var broadcastServer = new UdpClient(12301);
while(/**/)
{
var broadcastclientEp = new IPEndPoint(IPAddress.Any, 0);
var broadcastclientRequestData = broadcastServer.Receive(ref broadcastclientEp);
// Reply to broadcast:
var responseData = new byte[]{ /* Whatever */}
broadcastServer.Send(responseData, responseData.Length, broadcastclientEp);
}
}
服务器端多播:
// Listen for multicast
Task.Run(() =>
{
var multicastServer = new UdpClient(12302);
multicastServer.JoinMulticastGroup(IPAddress.Parse("239.255.255.253"));
while(/**/)
{
var multicastclientEp = new IPEndPoint(IPAddress.Any, 0);
var multicastclientRequestData = multicastServer.Receive(ref multicastclientEp);
// Reply to multicast:
var responseData = new byte[]{ /* Whatever */}
multicastServer.Send(responseData, responseData.Length, multicastclientEp);
}
}
如果客户端和服务器组件都在同一台计算机上运行,则广播和多播都按预期工作。
如果客户端和服务器组件位于同一子网中的不同计算机上,则广播工作,多播仅在一个方向上工作(给定 WLAN 拓扑中的两台计算机,当其中一台处于服务器角色时,多播工作,但不是反过来)。
如果客户端和服务器组件位于同一公司网络中的不同子网上,则广播或多播都不起作用。
我想让它跨子网可靠地工作。根据我目前了解到的情况,我知道广播不会起作用,但多播应该。
选择多播地址和/或端口号有什么魔力吗?换句话说,是否有特定的地址和端口我应该或不应该使用它来可靠地工作,而不管网络拓扑如何?是否存在通常被过滤或通常保持打开的地址/端口组合?有没有我忽略的配置选项?
【问题讨论】:
-
组播并不意味着跨子网使用。问题是子网中有很多多播和广播消息。当您允许多播通过子网时,您最终会用这些消息淹没子网。子网由掩码定义。因此,仔细设计您的网络掩码可能会解决问题。您可能希望使用一个使用 TCP 或 UDP 连接子网并在子网之间转发特定多播消息的网桥。一些路由器具有限制允许在子网之间传递的多播消息的设置。
-
@jdweng 感谢您的信息。它确实让我想知道服务发现如何适用于软件产品许可证服务器或 LAN 被分成多个子网的打印机。它们是否仅在子网内工作,是否需要明确的路由器配置,还是使用 SLP 风格的广播/多播以外的其他技术?
-
您正在创建一个多播网桥,您可以在该网桥上搜索。网桥的通用术语是端口转发,它是将消息从一个子网移动到另一个子网的通用术语。端口转发的类型取决于您需要转发的物理流量和流量(或不转发,以免网络泛滥)。如果您尝试从纽约转发到加利福尼亚,您将使用链接中的 Cisco 路由器。在同一个房间里,您可以只更改路由器上的设置来传递数据。端口转发可以通过软件或硬件来完成。
-
只有广播消息会被路由器阻止。通常 IP 地址(或计算机名称)是硬编码的,不会被发现。在子网之外,使用使用 IP 地址和掩码的 IP 路由或使用 ARP 协议来查找子网之外的设备或服务器具有计算机列表的 DHCP。子网有一个网关,用作查找子网外设备的默认路由。网络就像一个树状结构,其中子网是叶子,网关通向根,即全球互联网。