如何为具有2个网卡的UDP多播设置套接字? [英] How to set up a socket for UDP multicast with 2 network cards present?

查看:202
本文介绍了如何为具有2个网卡的UDP多播设置套接字?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用套接字和c ++(c)获得udp多播数据。我有一个服务器有2个网卡,所以我需要绑定到特定的接口。目前我在另一台只有一个网卡的服务器上进行测试。

I'm trying to get udp multicast data using sockets and c++ (c). I have a server with 2 network cards so I need to bind socket to specific interface. Currently I'm testing on another server that has only one network card.

当我使用INADDR_ANY时,我可以看到udp数据,当我绑定到特定的接口,看到任何数据。函数inet_addr没有失败(我现在取消了检查返回值)。

When I use INADDR_ANY I can see the udp data, when I bind to specific interface I don't see any data. Function inet_addr is not failing (I removed checking for return value for now).

代码如下。
在具有一个网卡的服务器上,我的IP地址为10.81.128.44。当我运行时,我收到数据:
./client 225.0.0.37 12346

Code is bellow. On a server with one network card, my IP address is 10.81.128.44. I receive data when I run as: ./client 225.0.0.37 12346

这给我没有数据:
./client 225.0.0.37 12346 10.81.128.44

This gives me no data: ./client 225.0.0.37 12346 10.81.128.44

有任何建议吗? (希望代码编译,我删除了评论...)

Any suggestions? (Hope the code compiles, I removed comments ...)

   #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <time.h>
    #include <string.h>
    #include <stdio.h>

    #include <iostream>
    #include <string>

    using namespace std;

    #define HELLO_PORT 12345
    #define HELLO_GROUP "225.0.0.37"
    #define MSGBUFSIZE 256

    int main(int argc, char *argv[])
    {
        string source_iface;
        string group(HELLO_GROUP);
        int port(HELLO_PORT);

        if (!(argc < 2)) group = argv[1];
        if (!(argc < 3)) port = atoi(argv[2]);
        if (!(argc < 4)) source_iface = argv[3];

        cout << "group: " << group << " port: " << port << " source_iface: " << source_iface << endl;

        int fd;
        if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
        {
            perror("socket");
            exit(1);
        }

        u_int yes = 1;
        if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0)
        {
            perror("Reusing ADDR failed");
            exit(1);
        }

        struct sockaddr_in addr;
        memset(&addr, 0, sizeof(addr));
        addr.sin_family = AF_INET;
        addr.sin_port = htons(port);
        addr.sin_addr.s_addr = (source_iface.empty() ? htonl(INADDR_ANY) : inet_addr(source_iface.c_str()));

   if (bind(fd,(struct sockaddr *)&addr, sizeof(addr)) < 0)
   {
        perror("bind");
        exit(1);
   }

   struct ip_mreq mreq;
   mreq.imr_multiaddr.s_addr = inet_addr(group.c_str());
   mreq.imr_interface.s_addr = (source_iface.empty() ? htonl(INADDR_ANY) : inet_addr(source_iface.c_str()));

    if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
    {
        perror("setsockopt");
        exit(1);
    }

    socklen_t addrlen;
    int nbytes;
    char msgbuf[MSGBUFSIZE];

   while (1)
    {
        memset(&msgbuf, 0, MSGBUFSIZE);

        addrlen = sizeof(addr);
        if ((nbytes = recvfrom(fd, msgbuf, MSGBUFSIZE, 0, (struct sockaddr *)&addr, &addrlen)) < 0)
        {
            perror("recvfrom");
            exit(1);
        }
       cout.write(msgbuf, nbytes);
        cout.flush();
    }

    return 0;
}

提前感谢...

推荐答案

在进行一些搜索和测试之后,我发现了这里< a>当绑定 udp组播套接字我们指定端口和离开地址空eg指定 INADDR_ANY

After some searching and testing I found out here that when binding udp multicast socket we specify port and leave address empty e.g. specify INADDR_ANY.

因此,以下

addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = (source_iface.empty() ?
                        htonl(INADDR_ANY) : 
                        inet_addr(source_iface.c_str()));

应如下所示:


COMMENT :如果我理解您的代码,
应该绑定到您的多播
地址而不是通配符地址。如果
绑定到通配符地址,
将能够在您的组播端口上接收单播
数据包。
绑定到您的多播地址将
防止这一点,并确保您只能获得
组播数据包在该端口。

COMMENT: If I understand your code you should be binding to your multicast address not the wildcard address. If you bind to the wildcard address you will be able to receive unicast packets on your multicast port. Binding to your multicast address will prevent this and ensure you only get multicast packets on that port.

:修复了基于上述注释的代码,绑定到多播地址,
存储在'group',而不是
INADDR_ANY只接收发送到
多播地址的多播包。

EDIT: Fixed the code based on above comment, binding to multicast address, stored in 'group', as opposed to INADDR_ANY to receive only multicast packets sent to multicast address.



addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = (group.empty() ?
                        htonl(INADDR_ANY) :
                        inet_addr(group.c_str()));

这解决了这个问题。添加 IP_MULTICAST_IF 不会有帮助,因为这是为了选择发送udp数据的特定接口,上面的问题在接收端。

This solved the problem. Adding IP_MULTICAST_IF will not help because that is for selecting specific interface for sending udp data, the problem above was on receiving side.

这篇关于如何为具有2个网卡的UDP多播设置套接字?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆