系统相关
首页 > 系统相关> > 在同一端口上接收多个多播源 – C,Linux

在同一端口上接收多个多播源 – C,Linux

作者:互联网

我有一个应用程序从同一端口上的多个组播源接收数据.我能够收到数据.但是,我试图考虑每个组的统计数据(即收到的消息,接收的字节数),并且所有数据都混淆了.有谁知道如何解决这个问题?如果我试着查看发件人的地址,那么它不是多播地址,而是发送机器的IP.

我使用以下套接字选项:

struct ip_mreq mreq;         
mreq.imr_multiaddr.s_addr = inet_addr("224.1.2.3");         
mreq.imr_interface.s_addr = INADDR_ANY;         
setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));

并且:

setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &reuse, sizeof(reuse));

解决方法:

[编辑澄清bind()实际上可能包含多播地址.]

因此,应用程序正在连接多个多播组,并将发送到其中任何一个的消息接收到同一端口. SO_REUSEPORT允许您将多个套接字绑定到同一端口.除端口外,bind()还需要一个IP地址. INADDR_ANY是一个包罗万象的地址,但也可以使用IP地址,包括多播地址.在这种情况下,只有发送到该IP的数据包才会被传送到套接字.即您可以创建多个套接字,每个多播组一个. bind()每个套接字到(group_addr,port),并加入group_addr.然后,发往不同组的数据将显示在不同的套接字上,您将能够以这种方式区分它.

我测试了以下适用于FreeBSD:

#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/param.h>
#include <unistd.h>
#include <errno.h>

int main(int argc, const char *argv[])
{
    const char *group = argv[1];

    int s = socket(AF_INET, SOCK_DGRAM, 0);
    int reuse = 1;
    if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &reuse, sizeof(reuse)) == -1) {
        fprintf(stderr, "setsockopt: %d\n", errno);
        return 1;
    }

    /* construct a multicast address structure */
    struct sockaddr_in mc_addr;
    memset(&mc_addr, 0, sizeof(mc_addr));
    mc_addr.sin_family = AF_INET;
    mc_addr.sin_addr.s_addr = inet_addr(group);
    mc_addr.sin_port = htons(19283);

    if (bind(s, (struct sockaddr*) &mc_addr, sizeof(mc_addr)) == -1) {
        fprintf(stderr, "bind: %d\n", errno);
        return 1;
    }

    struct ip_mreq mreq;
    mreq.imr_multiaddr.s_addr = inet_addr(group);
    mreq.imr_interface.s_addr = INADDR_ANY;
    setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));

    char buf[1024];
    int n = 0;
    while ((n = read(s, buf, 1024)) > 0) {
        printf("group %s fd %d len %d: %.*s\n", group, s, n, n, buf);
    }
}

如果您针对不同的多播地址运行多个此类进程,并向其中一个地址发送消息,则只有相关进程才会收到该进程.当然,在您的情况下,您可能希望在一个进程中拥有所有套接字,并且您将必须使用select或poll或等效函数来全部读取它们.

标签:c-3,linux,sockets,port,multicast
来源: https://codeday.me/bug/20190923/1813312.html