在同一端口上Receving多个组播源 - C,Linux的 [英] Receving multiple multicast feeds on the same port - C, Linux

查看:265
本文介绍了在同一端口上Receving多个组播源 - C,Linux的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个从多个组播源接收相同的端口上的数据的应用程序。我能够接收数据。不过,我试图解释每个组的统计数据(即收到封邮件,接收的字节),所有数据被混淆了。有谁知道如何解决这个问题呢?如果我尝试看看发件人的地址,它不是组播地址,而是IP发送机器的。

I have an application that is receiving data from multiple multicast sources on the same port. I am able to receive the data. However, I am trying to account for statistics of each group (i.e. msgs received, bytes received) and all the data is getting mixed up. Does anyone know how to solved this problem? If I try to look at the sender's address, it is not the multicast address, but rather the IP of the sending machine.

我使用以下套接字选项:

I am using the following socket options:

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

我AP preciate任何帮助!

I appreciate any help!!!

推荐答案

因此​​,应用程序正在加入几个组播组,并接收发送到其中的任何消息,以相同的端口。 SO_REUSEPORT 让你几个插座绑定到同一个端口。除了港口,绑定()需要一个IP地址。 INADDR_ANY 是一个包罗万象的地址,但IP地址也可以使用,包括组播之一。在这种情况下,只发送到该IP包将被传递到插座。即你可以创建几个插座,每个组播组。 绑定()每个插座的(GROUP_ADDR,端口),并加入GROUP_ADDR。然后数据给不同的组会显示在不同的插座,你就能够区分这种方式。

So the application is joining several multicast groups, and receiving messages sent to any of them, to the same port. SO_REUSEPORT allows you to bind several sockets to the same port. Besides the port, bind() needs an IP address. INADDR_ANY is a catch-all address, but an IP address may also be used, including a multicast one. In that case, only packets sent to that IP will be delivered to the socket. I.e. you can create several sockets, one for each multicast group. bind() each socket to the (group_addr, port), AND join group_addr. Then data addressed to different groups will show up on different sockets, and you'll be able to distinguish it that way.

我测试了在FreeBSD了以下工作:

I tested that the following works on 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);
    }
}

如果您运行几个这样的过程,对于不同的多播地址,并发送一个消息给一个地址,只有相关的过程将接收到它。当然,你的情况,你可能会想拥有所有的插座在一个过程中,你将不得不使用选择调查或等同于阅读它们。

If you run several such processes, for different multicast addresses, and send a message to one of the addresses, only the relevant process will receive it. Of course, in your case, you probably will want to have all the sockets in one process, and you'll have to use select or poll or equivalent to read them all.

这篇关于在同一端口上Receving多个组播源 - C,Linux的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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