2014-09-18 35 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()荷兰国际集团,只要你用它做的插座。