简体   繁体   中英

Why doesn't sender receive its multicast UDP packet if loopback is enabled?

Struggling past two days with the following questions: do the loopbacked packets go through access point back to sender if the sender is subscribed to the multicast group? Even if it's not the case, is it possible to force loopback through the AP?

Also, why isn't loopback working with the following code?

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");
}

Any help appreciated.

setsockopt()的参数应为int,而不是无符号字符。

Just struggled with the same problem. Linux will not mirror the packet on the same socket even if it matches the address:port. You should create another socket udp_socket_receiver the same way as your udp_socket and recvfrom will work. Looks like IP_MULTICAST_LOOP means to loop back multicast packets locally on all listeners except the sender socket.

do the loopbacked packets go through access point back to sender if the sender is subscribed to the multicast group?

I don't really know for sure, but at first glance the answer is a fat No . If the gateway bounces back the packet to where it came from, you would be duplicating traffic, and that defeats the point of multicast.

However, the sender will still receive the message because anyone in the local network subscribed to the group will receive the message, and the sender is subscribed.

Even if it's not the case, is it possible to force loopback through the AP?

I don't know, but you likely don't need that. See below.

why isn't loopback working with the following code?

Because you forgot to bind the socket. You're not telling the socket where is it supposed to listen, so even though the multicast might well be bouncing properly, UDP is dropping the packet because it's attached to a random port, which is likely not 8888.

Add the following chunk between the socket() and the setsockopt(IP_ADD_MEMBERSHIP) one. Works for me:

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;
}

You should also probably be close() ing the socket whenever you're done with it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM