c语言 - 如果启用了环回,为什么发送方不会收到其组播 UDP 数据包?



在过去的两天里,我们一直在努力解决以下问题:如果发送方订阅了多播组,环回数据包会通过接入点返回到发送方吗?即使不是这样,有可能通过AP强制回送吗?

另外,为什么环回不能使用以下代码?

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

感谢您的帮助。

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

刚刚遇到了同样的问题。Linux不会在同一个套接字上镜像数据包,即使它与地址:port匹配。您应该以与udp_socket和recvfrom相同的方式创建另一个套接字udp_socket_receiver。看起来IP_MULTICAST_LOOP意味着在除发送方套接字之外的所有侦听器上本地循环回多播数据包。

如果发送方订阅了多播组,环回的数据包会通过接入点返回到发送方吗?

我真的不确定,但乍一看,答案是一个肥胖的。如果网关将数据包反弹到它的来源,那么您将复制流量,这就破坏了多播的意义。

但是,发件人仍然会收到该消息,因为本地网络中订阅该组的任何人都会收到消息,并且发件人已订阅。

即使不是这样,有可能通过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(),只要你完成了套接字。

最新更新