17

INADDR_ANYマクロを使用せに、UDP / マルチキャスト ソケットを特定のインターフェイスにバインドするように、マルチキャスト リスナー / 送信者の例を変更しようとしています。

インターフェイスの IPv4 アドレスを所有しています。以下を試してみましたが、ソケットが UDP (ユニキャスト、ブロードキャスト、マルチキャスト) パケットを受信しません。

struct sockaddr_in addr;
int fd, nbytes;
socklen_t  addrlen;
struct ip_mreq mreq;

// my_ipv4Addr equals current IP as String, e.g. "89.89.89.89"

// create what looks like an ordinary UDP socket */
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
    perror("socket");
    exit(1);
}

// set up addresses
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
// [-]    addr.sin_addr.s_addr = htonl(INADDR_ANY); 
addr.sin_addr.s_addr = inet_addr(my_ipv4Addr); 
addr.sin_port = htons(port);

// bind socket
if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
    perror("bind");
    exit(1);
}

// use setsockopt() to request that the kernel join a multicast group
mreq.imr_multiaddr.s_addr = inet_addr(group);
// [-]    mreq.imr_interface.s_addr = htonl(INADDR_ANY);
mreq.imr_interface.s_addr = inet_addr(my_ipv4Addr);
if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq))< 0) {
    perror("setsockopt");
    exit(1);
}

編集:

私のプログラムの目的を説明しましょう。ネットワークがブロードキャスト/マルチキャストをサポートしているかどうかをチェックする小さなツールを書いています。したがって、私は 2 つのインターフェイスを持つシステムを所有しており、Interface1 経由でマルチキャスト パケットを送信し、Interface2 で受信しようとしています。ただし: パケットは、ループパック デバイスではなく、ネットワークを通過する必要があります。

アイデアは、thread1/interface1 でマルチキャスト ループバックを次のようにブロックすることです。

u_char loop = 0;
setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop));

そして、thread2/interface 2 インターフェイス固有でリッスンします。Tcpdump は、パケットが到着していることを示していますが、上記の構成ではドロップされています。

4

4 に答える 4

11

この場合、マルチキャスト グループにパケットを送信する ことしか できませんが、'my_ipv4Addr' から送信されたものであっても、パケットを受信することはできません。
addr.sin_addr.s_addr=inet_addr(my_ipv4Addr);
bind(sockfd,(SA*)&addr,sizeof(addr));


そうaddr.sin_addr.s_addrでなければなりませんhtonl(INADDR_ANY)

マルチキャストグループからすべてのパケットを受信できますが、指定したインターフェイス ( eth1 など ) ではなく、デフォルトのインターフェイス (おそらく eth0) でパケットを送信します。 したがって、これは効果がありません。
mreq.imr_interface.s_addr=inet_addr(my_ipv4Addr);




インターフェイス ETH1 を介してパケットを送信できますが 、ETH1 に関連付けられた IP から送信されたパケットのみを受信でき ます。他のクライアントからのパケットを受信することはできません。
setsockopt(sockfd,SOL_SOCKET,SO_BINDTODEVICE,ETH1,strlen(ETH1));



my_ipv4addr に関連付けられたインターフェイスを介してパケットを送信できます。 また、マルチキャスト グループ内の任意のクライアントから任意のパケットを受信できます。
mreq.imr_interface.s_addr=inet_addr(my_ipv4Addr);
setsockopt(sockfd,IPPROTO_IP,IP_MULTICAST_IF,&mreq.imr_interface,sizeof(struct in_addr);


于 2014-05-18T04:54:39.143 に答える
4
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY); 
//addr.sin_addr.s_addr = inet_addr(my_ipv4Addr); 
addr.sin_port = htons(port);

mreq.imr_multiaddr.s_addr = inet_addr(group);
// [-]    mreq.imr_interface.s_addr = htonl(INADDR_ANY);
mreq.imr_interface.s_addr = inet_addr(my_ipv4Addr);

あなたは私のようにあなたのコードを編集する必要があります。

于 2012-11-01T09:25:44.897 に答える
4

マルチキャスト トラフィックを受信するためにソケットをバインドするときに、ローカル アドレスにバインドすると、Windows 以外のシステムでマルチキャスト パケットが受信されなくなります。

特定のアドレスにバインドする機能を備えたUFTPのバージョン 3.6 をリリースしたときに、これを初めて発見しました。Windows では問題なく処理されますが、Linux システムではマルチキャスト パケットがアプリによって受信されませんでした。次のリリースでこの機能を削除する必要がありました。

マルチキャスト アドレスに直接バインドできることに注意してください。

addr.sin_addr.s_addr = inet_addr(group);

この場合、そのソケット上のそのマルチキャスト アドレスのトラフィックのみを受信します。ただし、受信するには、特定のインターフェイスでマルチキャスト グループに参加する必要があります。

同じソケットで複数のマルチキャスト アドレスからデータを受信する予定がある場合は、 にバインドする必要がありますINADDR_ANY

于 2012-10-12T17:03:37.183 に答える
0

理解のためにコードを簡略化したか、何かを見逃してしまいました。

これは構造体です

struct ip_mreqn {
    struct in_addr imr_multiaddr; /* IP multicast group
                                     address */
    struct in_addr imr_address;   /* IP address of local
                                     interface */
    int            imr_ifindex;   /* interface index */
};

ipmanページ-IP_ADD_MEMBERSHIP

しかし、あなたは言及しています

mreq.imr_interface.s_addr = inet_addr(my_ipv4Addr);

imr_interfaceとは何ですか?コンパイルしますか?

読みやすくするために上記の名前を書いたばかりの場合は、接続する特定のインターフェイスにインターフェイスインデックス(imr_ifindex)を入力してみましたか。

私の推測では、imrr_addressを残してインターフェイスインデックスのみを割り当てると、そのインターフェイスにバインドしてパケットを受信する必要があります。それが役立つかどうかを確認してください。

于 2012-10-06T22:14:08.570 に答える