簡體   English   中英

C 應用程序未接收多播

[英]C Application not recieving Multicast

我正在嘗試創建一個應用程序,它使用多播與本地網絡上的應用程序的其他實例通信(應用程序應該在 windows 和 linux 下工作)。

我是多播的新手,所以我嘗試使用在互聯網上找到的以下代碼:

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

該代碼成功發送了我可以在我的 android 手機上接收到的多播數據包(通過編譯完全相同的代碼並使用 Termux 編譯/執行)。

所以我知道代碼正在運行。 但這是我的問題:在 linux 和 windows 上,我無法收到數據包。 我可以發送它們(我的手機確實收到了來自兩者的數據包),但我無法接收。

令我驚訝的是,它與我的 linux 和 android 上的代碼完全相同(在 windows 上,只有一些使用 winsock2 的修改)。

此外,我可以看到我的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 是我在該網絡上的電話 IP 地址。

還可以看到我成功加入了組播組:

$ netstat -gn | grep 239.124.0.1

wlp58s0         1      239.124.0.1

所以我的問題是為什么我不能在 linux/windows 上接收多播數據包?

我需要更改我的代碼以接收它們嗎?

對於接收方,此代碼加入接口 0.0.0.0 上的多播組(指定為INADDR_ANY )。 這意味着它加入了被認為是默認接口的網絡接口。 如果這不是接收多播流量的同一個接口,您將不會收到數據包。

您正在接口 wlp58s0 上接收數據包,因此請查看該接口使用的 IP 地址,並在選擇要綁定的接口時使用該 IP。

例如,如果 wlp58s0 具有 IP 地址 192.168.1.2,則更改此:

mreq.imr_interface.s_addr = htonl(INADDR_ANY);

對此:

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