マルチキャストリスナー/送信者の例 を変更して、UDP /マルチキャストソケットを特定のインターフェースにバインドし、を使用しないINADDR_ANYマクロ。
インターフェイスの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を介して送信しますaパケットをマルチキャストし、Interface2で受信しようとします。しかし:パケットはネットワークを通過しますが、loopackデバイスではありません。
アイデアは、thread1/interface1のマルチキャストループバックを次のようにブロックすることです。
u_char loop = 0;
setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop));
そして、thread2/interface 2のインターフェイス固有のリッスン。 Tcpdumpは、パケットが到着していることを示していますが、上記の構成ではドロップされます。
とaddr.sin_addr.s_addr=inet_addr(my_ipv4Addr);
bind(sockfd,(SA*)&addr,sizeof(addr));
パケットはマルチキャストグループにのみ送信できます。
しかし、my_ipv4Addrから送信されたパケットであっても、パケットを受信することはできません。
したがって、_addr.sin_addr.s_addr
_はhtonl(INADDR_ANY)
でなければなりません。
とmreq.imr_interface.s_addr=inet_addr(my_ipv4Addr);
マルチキャストグループからすべてのパケットを受信できます。
しかし、それはデフォルトのインターフェース(おそらくeth0)でパケットを送信します、
指定したものではありません(eth1など)。
これは効果がありません。
とsetsockopt(sockfd,SOL_SOCKET,SO_BINDTODEVICE,ETH1,strlen(ETH1));
インターフェイスETH1を介してパケットを送信できます
ただし、ETH1に関連付けられたIPから送信されるパケットのみを受信できます。
他のクライアントからのパケットを受信することはできません。
とmreq.imr_interface.s_addr=inet_addr(my_ipv4Addr);
setsockopt(sockfd,IPPROTO_IP,IP_MULTICAST_IF,&mreq.imr_interface,sizeof(struct in_addr);
my_ipv4addrに関連付けられたインターフェイスを介してパケットを送信できます。
また、マルチキャストグループ内の任意のクライアントからの任意のパケットを受信できます。
マルチキャストトラフィックを受信するためにソケットをバインドする場合、ローカルアドレスにバインドすると、Windows以外のシステムでマルチキャストパケットを受信できなくなります。
特定のアドレスにバインドする機能を備えた [〜#〜] uftp [〜#〜] のバージョン3.6をリリースしたときに、これを最初に発見しました。 Windowsはそれをうまく処理しますが、Linuxシステムでは、マルチキャストパケットはアプリによって受信されませんでした。次のリリースで機能を削除する必要がありました。
マルチキャストアドレスに直接バインドすることが許可されていることに注意してください。
addr.sin_addr.s_addr = inet_addr(group);
この場合、そのソケット上のそのマルチキャストアドレスのトラフィックのみを受信します。ただし、受信するには、特定のインターフェイスのマルチキャストグループに参加する必要があります。
同じソケットで複数のマルチキャストアドレスからデータを受信する場合は、INADDR_ANY
にバインドする必要があります。
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);
あなたは私のようにあなたのコードを編集する必要があるだけです。
理解のためにコードを簡略化したか、何かを見逃したか、
これは構造体です
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 */
};
しかし、あなたは言及しています
mreq.imr_interface.s_addr = inet_addr(my_ipv4Addr);
imr_interfaceとは何ですか?コンパイルできますか?
読みやすくするために上記の名前を書いたばかりの場合は、インターフェースインデックス、つまりimr_ifindexを、接続する特定のインターフェースに入力してみましたか?.
私の推測では、imrr_addressを残してインターフェイスインデックスのみを割り当てると、そのインターフェイスにバインドしてパケットを受信するはずです。それが役立つかどうかを確認します。