c 用于 UDP 的 IPv4 多播侦听器在 ubuntu 上不接收数据包

问题描述 投票:0回答:1

我为工具编写了一个基于套接字的 udp 侦听器,它也应该能够接收多播。 对于 IPv6 这很好用,但 IPv4 就不行了。

我使用带有 IPv4 多播数据包的日志,并通过 tcpreplay 从另一台机器将其发送到我运行侦听器的 ubuntu 机器。我在 wireshark 上看到数据包。

我要找的包来源是10.21.1.98 30490端口 数据包的目的地是 239.21.0.2 端口 30490

我的代码编译工作正常,运行时也没有错误。 我把它放在一个独立文件中进行测试,所以它可能包含一些对这个问题无用的包含。

#include <sys/timerfd.h>
#include <stdlib.h>
#include <linux/sockios.h>  // for SIOCGSTAMP
#include <sys/ioctl.h>      // for ioctl
#include <errno.h>
#include <ifaddrs.h>
#include <signal.h>
#include <pthread.h>
#include <sys/socket.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <pthread.h>

#define MAX_PACKET_SIZE 2048

int main(int argc,char **argv)
{
    struct sockaddr_in server_in, client_in;
    struct ip_mreq mreq;

    int sockfd, n, i;
    char msgbuf[MAX_PACKET_SIZE];
    char src_ip[INET_ADDRSTRLEN];

    socklen_t client_len;

    // create socket and bind to IP & port
    sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (sockfd < 0) {
        perror("Openening socket");
        pthread_exit(NULL);
    }
    printf("Socket created.\n");

    server_in.sin_family = AF_INET;
    server_in.sin_port = htonl(30490);
    server_in.sin_addr.s_addr = htonl(INADDR_ANY);

    if (bind(sockfd, (struct sockaddr *)&server_in, sizeof(server_in)) < 0) {
        perror("Binding socket");
        pthread_exit(NULL);
    }
    printf("Socket bound successful.\n");

    // zero out structure
    bzero(&client_in, sizeof(client_in));
    client_len = sizeof(struct sockaddr_in);

    // join multicast group
    mreq.imr_interface.s_addr = inet_addr("169.254.255.10");    // interface ip address
    mreq.imr_multiaddr.s_addr = inet_addr("239.21.0.2");        // multicast dst group
    if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {
        perror("setsock multicast");
        pthread_exit(NULL);
    }
    printf("Joined Ipv4 Multicast group.\n");

    while(1) {
        printf("Listening...\n");
        n = recvfrom(sockfd, msgbuf, MAX_PACKET_SIZE, 0,
                    (struct sockaddr *)&client_in, &client_len);
        msgbuf[MAX_PACKET_SIZE] = '\0'; // add null terminator to end of buffer
        inet_ntop(AF_INET, &(client_in.sin_addr.s_addr), src_ip, INET_ADDRSTRLEN);
        printf("Message received. Src IP is %s\n", src_ip);
    }
}


我也不确定我是否需要将 ip 路由添加到所使用的接口,因为 IPv6 多播在没有和添加它的情况下工作得很好似乎并不能解决我的问题。

c ubuntu udp multicast ipv4
1个回答
0
投票

一个人可以从一个人的代码中强制混杂:

struct ifreq ifopts;  

//Set Promiscuous Mode
strncpy(ifopts.ifr_name, interface, IFNAMSIZ-1);
ioctl(sockfd, SIOCGIFFLAGS, &ifopts);
ifopts.ifr_flags |= IFF_PROMISC;
ioctl(sockfd, SIOCSIFFLAGS, &ifopts);

或在界面上设置

allmulti

ifconfig enp3s0 allmulti

https://serverfault.com/questions/679272/multicast-works-only-in-promiscuous-mode

© www.soinside.com 2019 - 2024. All rights reserved.