简体   繁体   English

C 应用程序未接收多播

[英]C Application not recieving Multicast

I am trying to create an application which uses multicast to speak to other instances of the application on the local network (application should work under windows and linux).我正在尝试创建一个应用程序,它使用多播与本地网络上的应用程序的其他实例通信(应用程序应该在 windows 和 linux 下工作)。

I am new to multicast, so I was trying to play with the following code I found on the internet:我是多播的新手,所以我尝试使用在互联网上找到的以下代码:

#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>

#define EXAMPLE_PORT 6000
#define EXAMPLE_GROUP "239.124.0.1"

// If argc == 0, recieve, else send
int main(int argc, char**argv)
{
    struct sockaddr_in addr;
    socklen_t addrlen = 0;
    int sock = 0, cnt = 0;
    struct ip_mreq mreq;
    char message[50];

    /* set up socket */
    sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock < 0) {
        perror("socket");
        exit(1);
    }

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

    if (argc > 1) {
        /* send */
        addr.sin_addr.s_addr = inet_addr(EXAMPLE_GROUP);
        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);
        }
    } else {
        /* receive */
        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);
        }
    }
}

The code successfully sends multicast packets that I can recieve on my android phone (by compiling the exact same code and using Termux to compile/execute).该代码成功发送了我可以在我的 android 手机上接收到的多播数据包(通过编译完全相同的代码并使用 Termux 编译/执行)。

So I know the code is working.所以我知道代码正在运行。 But here is my issue: On linux and windows, I cannot recieve the packets.但这是我的问题:在 linux 和 windows 上,我无法收到数据包。 I can send them (my phone does recieve the packets form both), but I can't recieve.我可以发送它们(我的手机确实收到了来自两者的数据包),但我无法接收。

What surprises me is that It is the exact same code on my linux and android (on windows there is just a few adaptations to use winsock2).令我惊讶的是,它与我的 linux 和 android 上的代码完全相同(在 windows 上,只有一些使用 winsock2 的修改)。

Furthermore, I can see that my linux indeed recieves the packets:此外,我可以看到我的linux确实收到了数据包:

$ sudo tcpdump -i wlp58s0 host 239.124.0.1

dropped privs to tcpdump
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on wlp58s0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
12:36:59.196616 IP 192.168.1.10.48727 > 239.124.0.1.6000: UDP, length 50
12:37:04.112507 IP 192.168.1.10.48727 > 239.124.0.1.6000: UDP, length 50
12:37:09.129963 IP 192.168.1.10.48727 > 239.124.0.1.6000: UDP, length 50
^C
4 packets captured
4 packets received by filter
0 packets dropped by kernel

192.168.1.10 is my phone IP address on that network. 192.168.1.10 是我在该网络上的电话 IP 地址。

I can also see that I successfully joined the multicast group:还可以看到我成功加入了组播组:

$ netstat -gn | grep 239.124.0.1

wlp58s0         1      239.124.0.1

So my question here is why can't I recieve the multicast packets on linux/windows?所以我的问题是为什么我不能在 linux/windows 上接收多播数据包?

And what do I need to change in my code to recieve them?我需要更改我的代码以接收它们吗?

For the receiver, this code joins the multicast group on interface 0.0.0.0 (specified as INADDR_ANY ).对于接收方,此代码加入接口 0.0.0.0 上的多播组(指定为INADDR_ANY )。 This means it joins on the network interface which is considered the default interface.这意味着它加入了被认为是默认接口的网络接口。 If this is not the same interface that is receiving multicast traffic, you won't receive the packets.如果这不是接收多播流量的同一个接口,您将不会收到数据包。

You're receiving the packets on interface wlp58s0, so see what IP address that interface is using and use that IP when choosing the interface to bind to.您正在接口 wlp58s0 上接收数据包,因此请查看该接口使用的 IP 地址,并在选择要绑定的接口时使用该 IP。

For example, if wlp58s0 has IP address 192.168.1.2, then change this:例如,如果 wlp58s0 具有 IP 地址 192.168.1.2,则更改此:

mreq.imr_interface.s_addr = htonl(INADDR_ANY);

To this:对此:

mreq.imr_interface.s_addr = inet_addr("192.168.1.2");

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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