簡體   English   中英

C - 選擇UDP /組播套接字的接口

[英]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 */
};

ip手冊頁 - IP_ADD_MEMBERSHIP

但你指的是

mreq.imr_interface.s_addr = inet_addr(my_ipv4Addr);

什么是imr_interface 它編譯?

如果您剛剛編寫了上面的名稱以獲得更好的可讀性,您是否嘗試將接口索引(即imr_ifindex)填充到要附加到的特定接口。

我的猜測是,如果你離開imrr_address並僅分配接口索引,它應該綁定到該接口並接收數據包。 看看是否有幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM