簡體   English   中英

UDP:為兩個不同的多播流偵聽同一端口

[英]UDP: Listening to the same port for two different multicast streams

我需要使用相同的端口監聽2個不同的組播組。 Program A將從230.0.0.1Program B230.0.0.2 兩個組播組都使用相同的port 2000 ,我無法控制它。

當我運行我的程序時,我在每個程序中都收到兩個組播流,即230.0.0.1230.0.0.2上廣播的數據包。 我懷疑問題是由於公共端口造成的。 這是我用來訂閱多播的代碼:

if( (sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0 ) {
  perror("socket");
  return -1;
}

if( setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0 ) {
  perror("setsockopt SO_REUSEADDR");
  return -1;
}

memset(&in_addr, 0, sizeof(in_addr));
in_addr.sin_family = AF_INET;
in_addr.sin_addr.s_addr = htonl(INADDR_ANY);
in_addr.sin_port = htons(2000);
if( bind(sd, (struct sockaddr*)&in_addr, sizeof(in_addr)) < 0 ) {
  perror("bind");
  return -1;
}

memset(&req, 0, sizeof(req));
inet_aton(intfc_ip, &req.imr_interface);
inet_aton("230.0.0.1", &req.imr_multiaddr);
if( setsockopt(sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &req, sizeof(req)) < 0 ) {
  perror("setsockopt IP_ADD_MEMBERSHIP");
  return -1;
}

recv()...

如何在每個程序中過濾特定的多播組?

如果你改變了

in_addr.sin_addr.s_addr = htonl(INADDR_ANY);

inet_aton(<your wanted IP address>, &in_addr.sin_addr.s_addr);

你可以獲得更多的成功。

(如果你改變你的程序使用getaddrinfo() ,你可以使它面向未來。)

“連接”可能就是你所需要的。 通常,對於連接TCP套接字,手冊頁還建議它可用於過濾掉來自其他地址的UDP數據包:

這里發布的手冊頁:

如果套接字sockfd的類型為SOCK_DGRAM,則addr是默認情況下發送數據報的地址, 以及接收數據報的唯一地址。

套接字代碼的問題是“recvfrom”只會為您提供發送數據包的源地址。 它不會告訴您數據包發送到的位置的IP地址。 您希望能夠檢查UDP數據包的目標地址,以便過濾掉發送到您不感興趣的多播IP地址的數據包。

您可以設置一個套接字選項,然后使用“recvmsg”而不是recv或recvfrom來獲取發送數據包的目標IP地址。

1)將setsockopt與IP_PKTINFO一起使用,以便為在套接字上接收的數據獲取傳遞到應用級別的目標IP地址。

int enable = 1;
setsockopt(sock, IPPROTO_IP , IP_PKTINFO , &enable, sizeof(enable));

2)使用recvmsg而不是recvfrom(或recv)來獲取UDP數據包發送到的目標地址。 我有一個名為“recvfromex”的輔助函數,它包裝了recvmsg並鏡像了recvfrom的功能 - 期望它有一個額外的參數供調用者獲取數據包的目標IP。

發布有點大風 - 但你可以從我的github項目中查看我的C ++代碼並獲取你需要的東西。

這里查看recvfromex函數

這里調用setsockopt調用的更多代碼示例(查找關於如何使用IP地址調用與IP_PKTINFO的函數“EnablePktInfo”)。 還包含IPV6和BSD的擴展。

(來自在同一端口上接收多個多播源的 答案 - C,Linux

ip(7)聯機幫助頁描述了一種可能的解決方案:

IP_MULTICAST_ALL(自Linux 2.6.31起)
此選項可用於將組播消息的傳遞策略修改為綁定到通配符INADDR_ANY地址的套接字。 參數是一個布爾整數(默認為1)。 如果設置為1,則套接字將從整個系統上全局加入的所有組接收消息。 否則,它將僅從已在此特定套接字上顯式連接的組(例如,通過IP_ADD_MEMBERSHIP選項)傳遞消息。

然后,您可以使用以下命令激活過濾器以接收已連接組的消息:

int mc_all = 0;
if ((setsockopt(sock, IPPROTO_IP, IP_MULTICAST_ALL, (void*) &mc_all, sizeof(mc_all))) < 0) {
    perror("setsockopt() failed");
}

暫無
暫無

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

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