15

同じポートで複数のマルチキャストソースからデータを受信して​​いるアプリケーションがあります。データを受信できます。ただし、各グループの統計(つまり、受信したメッセージ、受信したバイト)を考慮しようとしていますが、すべてのデータが混同されています。誰かがこの問題を解決する方法を知っていますか?送信者のアドレスを見ようとすると、それはマルチキャストアドレスではなく、送信側のマシンの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));
4

8 に答える 8

10

[実際にはマルチキャストアドレスが含まれている可能性があることを明確にするために編集bind()。]

したがって、アプリケーションは複数のマルチキャスト グループに参加し、それらのいずれかに送信されたメッセージを同じポートに受信します。SO_REUSEPORT複数のソケットを同じポートにバインドできます。ポートの他にbind()、IP アドレスが必要です。INADDR_ANYキャッチオール アドレスですが、マルチキャスト アドレスを含む IP アドレスも使用できます。その場合、その IP に送信されたパケットのみがソケットに配信されます。つまり、各マルチキャスト グループに 1 つずつ、複数のソケットを作成できます。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);
    }
}

異なるマルチキャスト アドレスに対して複数のこのようなプロセスを実行し、アドレスの 1 つにメッセージを送信すると、関連するプロセスだけがメッセージを受信します。もちろん、あなたの場合、おそらくすべてのソケットを 1 つのプロセスに入れたいと思うでしょう。それらをすべて読み取るには、または同等のものを使用する必要がありselectますpoll

于 2010-04-30T02:36:18.780 に答える
5

IPv4 を想定して、プラットフォームに応じてsetsockopt()and IP_PKTINFOorを使用します。IP_RECVDSTADDRこれを組み合わせるrecvmsg()か、すべてのパケットの送信元アドレス宛先アドレスWSARecvMsg()を見つけることができます。

Unix/Linux。どちらもIPv6 をIP_RECVDSTADDRサポートしている一方で、FreeBSD が使用されていることに注意してください。IP6_PKTINFO

Windows にもありますIP_ORIGINAL_ARRIVAL_IF

于 2010-05-02T10:06:05.127 に答える
3

交換

mc_addr.sin_addr.s_addr = htonl(INADDR_ANY);

mc_addr.sin_addr.s_addr = inet_addr (mc_addr_str);

それは私(Linux)にとって助けになります。アプリケーションごとに、1つのポートで別のmcastグループから別のmcastストリームを受け取ります。

また、VLCプレーヤーのソースを調べると、1つのポートで異なるmcastグループからの多くのmcast iptvチャネルが表示されますが、チャネルをどのように分離するかはわかりません.

于 2011-05-23T04:36:43.933 に答える
1

それぞれが異なるマルチキャスト グループ アドレスを参照する複数のソケットを使用し、各ソケットの統計を個別にカウントする必要がありました。

上記の回答にある「受取人の住所」を見る方法があれば、私にはわかりません。

私も時間がかかった重要なポイントの1つ-ほとんどのpythonの例のように、個々のソケットをそれぞれ空白のアドレスにバインドしたとき:

sock[i].bind(('', MC_PORT[i])

各ソケットで (すべてのマルチキャスト グループからの) すべてのマルチキャスト パケットを取得しましたが、役に立ちませんでした。これを修正するために、各ソケットを独自のマルチキャスト グループにバインドしました

sock[i].bind((MC_GROUP[i], MC_PORT[i]))

そして、それはうまくいきました。

于 2011-07-20T15:51:36.377 に答える
0

マルチキャスト アドレスは、パケット内の送信者のアドレスではなく、受信者のアドレスになります。受信者の IP アドレスを確認します。

于 2010-04-30T11:37:13.943 に答える
0

IIRC recvfrom() は、送信者ごとに異なる読み取りアドレス/ポートを提供します。

ソース送信者を識別するヘッダーを各パケットに入れることもできます。

于 2010-04-30T07:58:35.597 に答える