【问题标题】:Disable self-reception of UDP multicasts禁用 UDP 多播的自接收
【发布时间】:2017-08-17 00:26:30
【问题描述】:

我花了很多时间尝试理解 IP 多播。特别是,我想禁止数据包循环回多播组。

我只是将这段代码放在一起来举例说明我所看到的。

/*

example.c

 */

#include <sys/types.h>

#include <net/if.h>
#include <sys/socket.h>
#include <arpa/inet.h>

#include <pthread.h>
#include <time.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>

#define EXAMPLE_PORT 6000
#define EXAMPLE_GROUP "224.0.0.1"

const long MYSENDER = 0; // send thread ID
const long MYRECVR = 1; // recv thread ID

int status;
int sock;

void *sender(void *threadid);
void *receiver(void *threadid);

main(int argc) {
    pthread_t threads[2];
    struct sockaddr_in addr;

    /* Set up socket */
    sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (sock == -1) {
        perror("socket");
        exit(1);
    }

    status = pthread_create(&threads[MYRECVR], NULL, receiver, (void *) MYRECVR); // Start the server thread and check for error
    if (status) {
        fprintf(stderr, "Error: pthread_create(receiver) returned %d\n", status);
        exit(-1);
    }

    status = pthread_create(&threads[MYSENDER], NULL, sender, (void *) MYSENDER); // Start the client thread and check for error
    if (status) {
        fprintf(stderr, "Error: pthread_create(sender) returned %d\n", status);
        exit(-1);
    }

    pthread_join(threads[MYRECVR], NULL); // main() will wait for the server thread to complete
    pthread_join(threads[MYSENDER], NULL); // main() will wait for the client thread to complete
}

void *sender(void *threadid) {
    int c;
    char message[50];
    struct sockaddr_in addr;
    int addrlen, cnt;

    memset((char *) &addr, 0, sizeof (addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
    addr.sin_addr.s_addr = inet_addr(EXAMPLE_GROUP);
    addr.sin_port = htons(EXAMPLE_PORT);
    addrlen = sizeof (addr);

    fprintf(stderr, "Starting sender thread!\n");

    /* Send */
    while (1) {
        time_t t = time(0);
        sprintf(message, "time is %-24.24s", ctime(&t));
        printf("sending: %s\n", message);
        cnt = sendto(sock, message, sizeof (message), 0,
                (struct sockaddr *) &addr, addrlen);
        if (cnt < 0) {
            perror("sendto");
            exit(1);
        }
        sleep(5);
    }
    return 0;
}

void *receiver(void *threadid) {
    int opt = 1;
    char message[50];
    struct sockaddr_in addr;
    int addrlen, cnt;
    struct ip_mreq mreq;

    fprintf(stderr, "Starting receiver thread!\n");

    memset((char *) &addr, 0, sizeof (addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
    addr.sin_port = htons(EXAMPLE_PORT);
    addrlen = sizeof (addr);


    /* Receive */

    setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt));
    if (bind(sock, (struct sockaddr *) &addr, sizeof (addr)) < 0) {
        perror("bind");
        exit(1);
    }

    mreq.imr_multiaddr.s_addr = inet_addr(EXAMPLE_GROUP);
    mreq.imr_interface.s_addr = htonl(INADDR_ANY);
    if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
            &mreq, sizeof (mreq)) < 0) {
        perror("setsockopt mreq");
        exit(1);
    }

    while (1) {
        cnt = recvfrom(sock, message, sizeof (message), 0,
                (struct sockaddr *) &addr, &addrlen);
        if (cnt < 0) {
            perror("recvfrom");
            exit(1);
        } else if (cnt == 0) {
            break;
        }
        printf("%s: message = \"%s\"\n", inet_ntoa(addr.sin_addr), message);
    }
    return 0;
}

它运行良好并产生以下输出...

picozed@ubuntu:/tmp$ ./test
Starting receiver thread!
Starting sender thread!
sending: time is Wed Aug 16 19:23:29 2017
10.249.27.51: message = "time is Wed Aug 16 19:23:29 2017"
sending: time is Wed Aug 16 19:23:34 2017
10.249.27.51: message = "time is Wed Aug 16 19:23:34 2017"
^C
picozed@ubuntu:/tmp$

但是,我想防止消息被循环回...

【问题讨论】:

  • 您需要使用IP_MULTICAST_LOOP 选项调查setsockopt()
  • 我应该提到我确实使用了 setsockopt() 来禁用 IP_MULTICAST_LOOP,但数据包仍然会被环回..
  • 你当然应该,而且你也应该包含相关代码。可能不正确。

标签: c sockets network-programming udp multicast


【解决方案1】:

默认情况下,大多数操作系统会将传出的多播流量循环回本地计算机。如果要禁用此行为,则需要将IP_MULTICAST_LOOP 套接字选项设置为 0。

int opt=0;
if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, &opt, sizeof (opt)) < 0) {
    perror("setsockopt");
    exit(1);
}

【讨论】:

    猜你喜欢
    • 2011-05-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-07
    • 1970-01-01
    • 2014-08-15
    • 2018-11-07
    • 1970-01-01
    相关资源
    最近更新 更多