绑定多播(UDP)套接字是什么意思?

我在具有多个networking接口的主机之间使用组播UDP。 我正在使用boost :: asio,并且被2个操作接收器所迷惑:绑定,然后连接组。

为什么在绑定期间需要指定一个接口的本地地址?何时join每个组播组?

姐姐问题关于组播端口:因为在发送过程中,你发送到一个多播地址和端口,为什么在订阅一个多播组时,你只指定地址,而不是端口 – 在混淆调用指定的端口绑定。

注意:“join-group”是setsockopt(IP_ADD_MEMBERSHIP)一个包装,可以在同一个套接字上多次调用它,以订阅不同的组(通过不同的networking?)。 因此,在每次订阅一个组时,抛弃绑定调用并指定端口是非常有意义的。

从我看到的,总是绑定到“0.0.0.0”并指定join组时的接口地址,效果很好。 困惑。

在接收多播时绑定UDP套接字意味着指定从中接收数据的地址和端口(不是本地接口,如TCP接受器绑定的情况)。 在这种情况下指定的地址具有过滤作用,即套接字将只接收发送到该多路广播地址和端口的数据报,而不pipe套接字随后join了哪些组。 这解释了为什么当绑定到INADDR_ANY(0.0.0.0)时,我收到了发送到我的多播组的数据报,而当绑定到任何本地接口时,我什么也没有收到,即使数据报是在networking上发送的对应。

引自UNIX®networking编程第1卷,第3版:WR Stevens的套接字networkingAPI。 21.10。 发送和接收

[…]我们希望接收套接字绑定多播组和端口,比如239.255.1.2端口8888.(回想一下,我们可以绑定通配符IP地址和端口8888,但绑定多播地址阻止套接字接收任何其他数据报可能到达目的地端口8888.)然后,我们希望接收套接字join多播组。 发送套接字将发送数据包到这个相同的多播地址和端口,比如239.255.1.2端口8888。

“绑定”操作基本上是指“使用本地UDP端口发送和接收数据,换句话说,它分配的UDP端口专用于您的应用程序(对于TCP套接字也是如此)。

当绑定到“0.0.0.0”(INADDR_ANY)时,基本上告诉TCP / IP层使用所有可用的适配器进行侦听,并select最适合发送的适配器。 这是大多数套接字代码的标准做法。 只有当你想在特定的networking适配器上发送/接收时,你才不会为IP地址指定0。

同样,如果在绑定期间指定端口值为0,则操作系统将为该套接字分配一个随机可用的端口号。 所以我期望UDP多播,你绑定到INADDR_ANY在一个特定的端口号,多点传送stream量将被发送到。

需要“join多播组”操作(IP_ADD_MEMBERSHIP),因为它基本上告诉您的networking适配器不仅侦听目标MAC地址是您自己的以太网帧,还告知以太网适配器(NIC)侦听IP多播通信以及相应的多播以太网地址。 每个组播IP映射到组播以太网地址。 当您使用套接字发送到特定的多播IP时,以太网帧上的目标MAC地址将被设置为相应的多播IP的多播MAC地址。 join多播组时,您需要configurationNIC来侦听发送到同一MAC地址的stream量(除了自己的stream量外)。

没有硬件支持,多播将不会更有效,简单的广播IP消息。 连接操作还会告诉您的路由器/网关转发来自其他networking的多播通信。 (有人记得MBONE?)

如果您join一个多播组,该IP地址上所有端口的所有多播通信将由NIC接收。 只有发往绑定监听端口的stream量才会被TCP / IP协议栈传递给你的应用。 关于在多播订阅期间为什么指定端口 – 这是因为多播IP只是 – IP而已。 “端口”是上层协议(UDP和TCP)的一个属性。

您可以阅读更多关于多播IP地址如何映射到各个站点的多播以太网地址的信息。 维基百科的文章大致如下:

IANA拥有OUI MAC地址01:00:5e,因此组播报文使用以太网MAC地址范围01:00:5e:00:00:00 – 01:00:5e:7f:ff:ff。 这是23位的可用地址空间。 第一个八比特组(01)包括广播/多播比特。 28位多播IP地址的低23位映射到可用以太网地址空间的23位。

更正绑定多播(udp)套接字是什么意思? 只要在下面的引用中部分为真:

“绑定”操作基本上是指“使用本地UDP端口发送和接收数据,换句话说,它分配该UDP端口专用于您的应用程序

有一个特例。 如果应用了SO_REUSEADDR选项,多个应用程序可以共享相同的端口进行监听(通常对于多播数据报具有实用价值):

 int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); // create UDP socket somehow ... int set_option_on = 1; // it is important to do "reuse address" before bind, not after int res = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*) &set_option_on, sizeof(set_option_on)); res = bind(sock, src_addr, len); 

如果多个进程执行了这种“重用绑定”,则在该共享端口上接收到的每个UDP数据报将被传递给每个进程(提供自然联合多播stream量)。

a)尝试任何绑定(“独占”或“重复使用”)来自由港将是成功的

b)尝试“独占绑定”将失败,如果该端口已经“重用绑定”

c)尝试“重新使用绑定”将失败,如果某个进程保持“独占绑定”

将发送组播套接字与接收组播套接字区分开来也非常重要。

我同意以上关于RECEIVING多播套接字的所有答案。 OP注意到绑定RECEIVING skt到界面并没有帮助。 但是,必须将多播SENDING套接字绑定到接口。

对于多宿主服务器上的SENDING多播套接字,为每个要发送到的接口创build一个单独的套接字非常重要。 应该为每个接口创build绑定的SENDING skt。

  // This is a fix for that bug that causes Servers to pop offline/online. // Servers will intermittently pop offline/online for 10 seconds or so. // The bug only happens if the machine had a DHCP gateway, and the gateway is no longer accessible. // After several minutes, the route to the DHCP gateway may timeout, at which // point the pingponging stops. // You need 3 machines, Client machine, server A, and server B // Client has both ethernets connected, and both ethernets receiving CITP pings (machine A pinging to en0, machine B pinging to en1) // Now turn off the ping from machine B (en1), but leave the network connected. // You will notice that the machine transmitting on the interface with // the DHCP gateway will fail sendto() with errno 'No route to host' if ( theErr == 0 ) { // inspired by 'ping -b' option in man page: // -b boundif // Bind the socket to interface boundif for sending. struct sockaddr_in bindInterfaceAddr; bzero(&bindInterfaceAddr, sizeof(bindInterfaceAddr)); bindInterfaceAddr.sin_len = sizeof(bindInterfaceAddr); bindInterfaceAddr.sin_family = AF_INET; bindInterfaceAddr.sin_addr.s_addr = htonl(interfaceipaddr); bindInterfaceAddr.sin_port = 0; // Allow the kernel to choose a random port number by passing in 0 for the port. theErr = bind(mSendSocketID, (struct sockaddr *)&bindInterfaceAddr, sizeof(bindInterfaceAddr)); struct sockaddr_in serverAddress; int namelen = sizeof(serverAddress); if (getsockname(mSendSocketID, (struct sockaddr *)&serverAddress, (socklen_t *)&namelen) < 0) { DLogErr(@"ERROR Publishing service... getsockname err"); } else { DLog( @"socket %d bind, %@ port %d", mSendSocketID, [NSString stringFromIPAddress:htonl(serverAddress.sin_addr.s_addr)], htons(serverAddress.sin_port) ); } 

没有这个修复,多播发送会间歇性地得到sendto()errno'没有路由到主机'。 如果有人可以解释为什么拔下DHCP网关会导致Mac OS X多播SENDING套接字混淆,我很乐意听到它。

Interesting Posts