[英]C - choose interface for UDP/multicast socket
我試圖修改多播偵聽器/發送器示例以將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);
}
編輯:
讓我解釋一下我的計划的目的。 我正在編寫一個小工具,如果網絡支持廣播/多播,它將檢查。 因此,我擁有一個帶有兩個接口的系統,並通過Interface1發送一個多播數據包並嘗試通過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並僅分配接口索引,它應該綁定到該接口並接收數據包。 看看是否有幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.