我使用具有多个网络接口的主机之间的多播UDP。 我使用boost :: ASIO,而且我在2个操作接收机困惑已经做出:绑定,然后加入群。
为什么你需要指定接口的本地地址,绑定过程中,当你做到这一点与您加入的每个组播组?
小姑问题关于多播端口:由于在发送过程中,发送到多播地址和端口,为什么,订阅一个组播组中,只指定地址,而不是端口 - 在混乱调用被指定的端口绑定。
注:“加入群”是在包装setsockopt(IP_ADD_MEMBERSHIP)
其作为记录,可称为同一插座上多次订阅不同的群体(在不同的网络?)。 因此,它将使完美的意义沟绑定调用和指定端口每次我订阅论坛的时间。
从我所看到的,总是结合“0.0.0.0”和加入该组时指定的接口地址,工作得非常好。 困惑。
绑定一个UDP套接字时接收多播装置到指定的地址和端口从其接收数据(不是本地接口,如对于TCP受体结合的情况下)。 在这种情况下,指定的地址具有过滤作用,即套接字将只接收发送到多播地址和端口,不管什么团体由插座随后加入数据报。 这就解释了为什么(0.0.0.0)绑定到INADDR_ANY当我收到发送到我的组播组的数据报,而当绑定到任何本地接口我没有收到任何东西,即使正在网络上发送的数据包到该接口对应。
从UNIX®网络编程第1卷报价,第三版:由WR史蒂文斯套接字联网API。 21.10。 发送和接收
[...]我们希望接收套接字绑定的多播组和端口,说239.255.1.2的端口8888(回想一下,我们可以只绑定通配符IP地址和端口号8888,但结合多播地址防止插座从接收可能到帐往端口8888的任何其它数据包),然后我们想接收套接字来加入组播组。 发送套接字将数据报发送给这个相同的组播地址和端口,说239.255.1.2的端口8888。
在“绑定”操作基本上是说,“使用本地UDP端口用于发送和接收数据。换句话说,它分配UDP端口为您的应用程序独占使用。(同样适用于TCP套接字真)。
当您绑定到“0.0.0.0”( INADDR_ANY
),你基本上说的是TCP / IP层使用所有可用适配器的听力和选择最佳适配器发送。 这是大多数套接字代码标准的做法。 你不会对IP地址指定为0的唯一情况是当你想要发送/接收特定的网络适配器上。
同样,如果你绑定在指定为0,端口值,操作系统将指派该插座随机提供的端口号。 所以,我希望为UDP组播,绑定到INADDR_ANY在哪里组播流量预计将发送至特定端口号。
“加入组播组”操作( IP_ADD_MEMBERSHIP
需要的),因为它主要是告诉您的网络适配器听不仅为以太网数据帧在目的MAC地址是你自己的,它也告诉了以太网适配器( NIC )来监听IP组播流量以及为相应的组播以太网地址。 每个组播IP映射到多播以太网地址。 当使用一个插座以发送到一个特定的多播IP,以太网帧的目的地MAC地址被设置为相应的多播MAC地址的多播IP。 当你加入某个组播组,正在配置的NIC监听发送到相同的MAC地址(除了它自己)的交通。
如果没有硬件支持,组播也不会有任何比普通的广播IP报文更高效。 加入操作也告诉您的路由器/网关与其它网络的组播转发。 (还有人记得MBONE?)
如果你加入某个组播组,全部用于对IP地址的所有端口的组播流量将被网卡接收。 只有发往您绑定的监听端口的流量会获得通过的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数据报将被输送至每个处理(提供与多播流量自然关节)的。
下面是关于在少数情况下会发生什么情况的详细信息:
任何绑定(“独家”或“再利用”)到自由港的尝试将会成功
试图“专一结合”会,如果该端口已经是“重用绑定”失败
试图“重用结合”会失败,如果某些过程使“专一结合”
这也是非常重要的,从接收多播插槽区分发送组播插座。
我同意上述关于接收多播套接字的所有问题的答案。 该OP指出,接收插座结合的接口并没有帮助。 然而,有必要结合组播SENDING插座的接口。
对于多宿主服务器上发送组播插座,这是非常重要的创造要发送到每个接口都有一个单独插座。 一个绑定的发送者的套接字应该为每个接口创建。
// 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()错误号“没有到主机的路由”。 如果任何人都可以阐明为什么拔掉一个DHCP网关光引起的Mac OS X组播SENDING插座感到困惑,我很乐意听到它。