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.

我正在尝试使用socket和c++ (c)获取udp多播数据,我有一个服务器,有2张网卡,所以我需要将socket绑定到特定的接口。目前我正在测试另一个只有一张网卡的服务器。

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).

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

Code is below. 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

下面的代码。在拥有一张网卡的服务器上,我的IP地址是10.81.128.44。当我运行为:./客户225.0.37 12346时,我收到数据

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

这没有给我数据:./客户225.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;
}

Thanks in advance ...

提前谢谢…

2 个解决方案

#1


8

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.

在进行了一些搜索和测试之后,我发现在绑定udp多播套接字时,我们指定端口并将地址留空,例如指定INADDR_ANY。

So the following

所以以下

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()));

should be look like:

应该看起来像:

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.

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

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.

编辑:修正基于上述评论的代码,绑定到多播地址,存储在“组”中,而不是INADDR_ANY只接收发送到多播地址的多播数据包。

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()));

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.

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

更多相关文章

  1. 如果后台的SVN服务器IP地址更改了,如何修改客户端的连接url呢?
  2. Linux 修改ip地址
  3. linux配置虚拟IP地址方法
  4. 使用.NetCore在Linux上写TCP listen 重启后无法绑定地址
  5. Linux系统下用C语言获取MAC地址
  6. Red Hat Linux下如何修改网卡MAC地址
  7. 一些下载交叉编译环境的地址
  8. PLSQL并非所有变量都已绑定
  9. 如何使用SQL语句查到当前SQL SERVER 2000服务器的IP地址

随机推荐

  1. eruda 一个被人遗忘的调试神器
  2. Linux性能优化(五)——性能监控工具
  3. 小姐姐对不喜欢的男孩到底有多残忍?
  4. 007. 整数反转 | Leetcode题解
  5. 专属开发者的福利,1000刀+的羊毛在等你
  6. 008. 字符串转换整数 (atoi) | Leetcode
  7. 010. 正则表达式匹配 | Leetcode题解
  8. Linux 目录
  9. 016. 最接近的三数之和 | Leetcode题解
  10. 011. 盛最多水的容器 | Leetcode题解