2014-09-18 40 views
0

在以下兩個問題中掙扎兩天:如果發送方訂閱了多播組,則環回數據包是否會通過接入點返回給發送方?即使情況並非如此,是否有可能強制通過AP進行環回?如果啓用了環回,爲什麼發送者不能收到其多播UDP數據包?

此外,爲什麼不使用下面的代碼循環工作?

char * server_addr_name = "239.255.0.1"; // multicast group 
int port_number = 8888; 
int enable_loopback = 1; 
int udp_socket; 
struct message msg; // random message 
char buffer[BUFFER_SIZE]; 

/* create socket */ 
struct sockaddr_in server_addr, rcv_addr; 
socklen_t server_addr_size = sizeof(struct sockaddr_in); 
socklen_t rcv_addr_size = sizeof(struct sockaddr_in); 

/* initialize socket */ 
memset(& server_addr, 0, sizeof(struct sockaddr_in)); 
server_addr.sin_family = AF_INET; 
server_addr.sin_addr.s_addr = inet_addr(server_addr_name); 
server_addr.sin_port = htons(port_number); 
if ((udp_socket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { 
    fprintf(stderr, "Error initializing UDP socket.\n"); 
    exit(EXIT_FAILURE); 
} 

struct ip_mreq mreq; 
mreq.imr_multiaddr.s_addr = inet_addr(server_addr_name); 
mreq.imr_interface.s_addr = htonl(INADDR_ANY); 
if (setsockopt(udp_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, & mreq, sizeof(mreq)) < 0) { 
    fprintf(stderr, "Error on setting multicast membership on socket.\n"); 
    exit(EXIT_FAILURE); 
} 
unsigned char do_enable = (unsigned char) enable_loopback; 
if (setsockopt(udp_socket, IPPROTO_IP, IP_MULTICAST_LOOP, 
       & do_enable, sizeof(do_enable)) < 0) { 
    fprintf(stderr, "Error on setting multicast loopback on socket.\n"); 
    exit(EXIT_FAILURE); 
} 

int read_size = 0; 
while (1) { 

    /* send the packet */ 
    if (sendto(udp_socket, &msg, sizeof(struct message), 0, 
      (struct sockaddr *) & server_addr, server_addr_size) == -1) { 
     fprintf(stderr, "Error on sending UDP packet.\n"); 
    } 
    else 
     printf("Sent my message.\n"); 

    /* get response from the server/multicast address */ 
    read_size = recvfrom(udp_socket, buffer, BUFFER_SIZE, 0, 
          (struct sockaddr *) & rcv_addr, & rcv_addr_size); 
    if (read_size < 1) 
     break; 
    else 
     printf("Got my packet!\n"); 
} 

任何幫助表示讚賞。

+0

你如何測試?你是否在發送者和接收者在同一臺機器上的測試環境中?如果是這樣,我會建議嘗試使用127.0.0.1作爲IP,並修改您的主機文件添加一行:127.0.0.1主機名,其中主機名是計算機名。我有時會遇到這個問題。 – Picarus 2014-09-19 08:27:42

+0

@Picarus這隻會讓一切變得更糟。 – EJP 2014-09-19 09:37:22

+0

@EJP,我的觀點是第一,調試問題以查看它是否是網絡問題,其次,有時表示問題不在代碼中,而是在系統配置中。你爲什麼認爲這可能會更糟?它可以解決問題,但它可以幫助帶來光線 – Picarus 2014-09-20 10:05:48

回答

1

setsockopt()的參數應該是一個int而不是一個無符號的char。

+0

那麼,它仍然沒有解決我的問題。根本沒有迴環的跡象。 – user330293 2014-09-19 06:38:10

+0

它究竟是什麼?什麼代碼更改? – EJP 2014-09-19 09:36:44

+0

unsigned char do_enable - > int do_enable – user330293 2014-09-19 14:11:44

1

只是與同樣的問題掙扎。即使它與地址:端口匹配,Linux也不會​​在同一個套接字上鏡像數據包。 你應該創建另一個套接字udp_socket_receiver,就像你的udp_socket和recvfrom可以工作一樣。看起來像IP_MULTICAST_LOOP意味着在除發送方套接字以外的所有偵聽器上本地回送多播數據包。

+1

你應該分享你的想法通過列出的DOS – 2015-05-11 13:00:30

+0

Tthis是錯誤的。 Linux(我在4.4.0)將默認情況下將多播數據報映射到發送套接字。您只需確保套接字綁定到多播sockaddr,訂閱該組(使用'ip maddr'來檢查),並且未連接。 – wick 2017-06-26 22:03:26

0

如果發送者訂閱了多播組,那麼環回數據包是否會經過接入點返回給發送者?

我真的不知道,但乍一看答案是胖沒有。如果網關將數據包反彈回來,那麼您將會複製流量,並且會破壞多點傳送。

但是,發件人仍然會收到該郵件,因爲訂閱該組的本地網絡中的任何人都將收到該郵件,並且發件人已訂閱。

即使不是這種情況,是否可以強制通過AP進行環回?

我不知道,但你可能不需要那個。見下文。

爲什麼不使用以下代碼進行回送工作?

因爲您忘記了bind的插座。你沒有告訴套接字應該在哪裏聽,所以即使多路廣播可能會彈跳得很好,UDP也會丟棄數據包,因爲它連接到了一個隨機端口,可能不是8888.

添加在socket()setsockopt(IP_ADD_MEMBERSHIP)之間。工作對我來說:

struct sockaddr_in src; 
memset(&src, 0, sizeof(src)); 
src.sin_family = AF_INET; 
src.sin_port = htons(port_number); 
src.sin_addr.s_addr = INADDR_ANY; 
if (bind(udp_socket, (struct sockaddr*)&src, sizeof(src))) { 
    perror("bind() failed"); 
    close(udp_socket); 
    return EXIT_FAILURE; 
} 

你也可能應該close()荷蘭國際集團,只要你用它做的插座。