0

ソース固有のマルチキャスト グループに参加し、udp マルチキャスト パケットを受信するプログラムを作成しました。

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <net/if.h>

typedef unsigned int        UINT32;

int join_ssm_group(int s, UINT32 group, UINT32 source, UINT32 inter) {
    struct ip_mreq_source imr; 
    imr.imr_multiaddr.s_addr  = group;
    imr.imr_sourceaddr.s_addr = source;
    imr.imr_interface.s_addr  = inter;
    return setsockopt(s, IPPROTO_IP, IP_ADD_SOURCE_MEMBERSHIP, (char *) &imr, sizeof(imr));  
}

UINT32 LISTEN_INTERFACE = inet_addr("10.10.1.2");

int main(int argc, char *argv[]) {

    if (argc<3) {
        printf(" Use: %s <group> <source> <port>", argv[0]);
        return 1;
    }

    //  Make socket 
    int sd = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);

    struct sockaddr_in Sender;
    socklen_t SenderAddrSize = sizeof( Sender );

    struct sockaddr_in binda;

    //  Bind it to listen appropriate UDP port
    binda.sin_family = AF_INET;
    binda.sin_port = htons( atoi(argv[3]));
      = INADDR_ANY;
    // binda.sin_addr.s_addr = LISTEN_INTERFACE;
    bind(sd,(struct sockaddr*)&binda, sizeof(binda));

    // Join to group
    join_ssm_group( sd, inet_addr(argv[1]), 
        inet_addr(argv[2]), 
        INADDR_ANY );

    char        buf[65536];
    UINT32      seq;

    while(1) {
        printf("try receive\n");
        int res=recvfrom(sd,(char*)buf,sizeof(buf),0, (struct sockaddr *)& Sender, &SenderAddrSize);
        printf("received\n");
        seq = *(UINT32*)buf;
        printf("scr=:%12s;\tseq=%6d;\tlen=%4d\n", inet_ntoa(Sender.sin_addr), seq, res);
    }

    return 0;
}

正常に動作しますが、私が使用していることに注意してくださいbinda.sin_addr.s_addr = INADDR_ANY;。netstat はこれを示します:

netstat -a | grep 16002
udp        0      0 0.0.0.0:16002           0.0.0.0:*

プログラムに変更すると、binda.sin_addr.s_addr = LISTEN_INTERFACE;動作が停止します-パケットを受信できず、ハングしrecvfromます。netstat はこれを示します:

netstat -a | grep 16002
udp        0      0 localhost.localdo:16002 0.0.0.0:*

どちらの場合も、tcpdump はデータがオンラインであることを示しているため、問題は、特定のインターフェイスでデータを受信できず、すべてのインターフェイスでのみデータを受信できないことです。私は RHEL 7 をチーム化して使用しています。LISTEN_INTERFACE は対応する VLAN の IP です。コードが機能しない理由とそのトラブルシューティング方法を教えてください。パフォーマンス上の理由から INADDR_ANY を使用したくありません。すべてのインターフェイスをリッスンすると、特定のインターフェイスをリッスンするよりもコストがかかります。

join_ssm_groupと との両方にLISTEN_INTERFACEを渡す upd もbinda.sin_addr.s_addr機能しません。ところで、このようなコードの同様の Windows バージョンは、Windows Server 2008 R2 の下の同じ PC で動作しますが、RHEL 7 では動作しません。これらを確認する必要があると思います。

  • RHEL 7 が必要なポートの必要なインターフェイスでデータを受信する場合 (答えははい、tcpdump によって証明されます)
  • ソケットが必要なポートの必要なインターフェイスでリッスンしている場合 (答えは「はい、netstat で証明されていますか?」)
  • 上記の両方の答えが「はい」の場合、への呼び出しがrecvfromデータを受信しない可能性はありますか?

おそらく、この質問は現在、C++ よりも RHEL 7 に関するものです。

4

1 に答える 1

1

マルチキャスト グループに参加するときは、リッスンしているのと同じインターフェイスを指定するか、ループ内のすべてのインターフェイスを介して参加する必要があります。

ただし、すべてのインターフェイスでリッスンするのが標準です。誰が接続できるかを制限する特定の理由がない限り、それは「遅い」わけではなく、「良い考え」です。

于 2014-11-27T20:21:01.423 に答える