linux - UDP 在同一台机器上广播?

标签 linux sockets udp broadcast

我写了一个广播器和一个监听器,它们系统上的特定端口接收。我为 listener 中的套接字使用了 REUSEADDR 选项,使 listener 的多个实例监视同一系统上的同一端口。

当我在不同的机器上运行监听器,并从另一台机器发送数据包时,所有监听器 都收到了数据包。但是当我在同一台机器上运行多个 listener 实例并且如果我尝试发送 udp 数据包时,只有 listener 的第一个实例获取数据包而不是全部。我想在同一台机器上广播 UDP 数据包,并希望所有的监听器都能接收到该数据包。我在 Linux 上。

我遵循了 Beej 指南。

编辑 01

监听代码

/*
** listener.c -- a datagram sockets "server" demo
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

#define MYPORT "4950"   // the port users will be connecting to

#define MAXBUFLEN 100

// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa)
{
        if (sa->sa_family == AF_INET) {
                return &(((struct sockaddr_in*)sa)->sin_addr);
        }

        return &(((struct sockaddr_in6*)sa)->sin6_addr);
}

int main(int argc, char *argv[])
{
        int sockfd;
        struct addrinfo hints, *servinfo, *p;
        int rv;
        int numbytes;
        struct sockaddr_storage their_addr;
        char buf[MAXBUFLEN];
        socklen_t addr_len;
        char s[INET6_ADDRSTRLEN];

        int reuse_addr = 1;


        memset(&hints, 0, sizeof hints);
        hints.ai_family = AF_UNSPEC; // set to AF_INET to force IPv4
        hints.ai_socktype = SOCK_DGRAM;
        hints.ai_flags = AI_PASSIVE; // use my IP

        if ((rv = getaddrinfo(NULL, MYPORT, &hints, &servinfo)) != 0) {
                fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
                return 1;
        }

        // loop through all the results and bind to the first we can
        for(p = servinfo; p != NULL; p = p->ai_next) {
                if ((sockfd = socket(p->ai_family, p->ai_socktype,
                                p->ai_protocol)) == -1) {
                        perror("listener: socket");
                        continue;
                }

                if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {

                        if(errno == EADDRINUSE)
                        {
                                if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
                                                &reuse_addr, sizeof reuse_addr) < 0)
                                        perror("setsockopt(): REUSEADDR\n"),exit(1);
                        }
                        else
                        {
                                close(sockfd);
                                perror("listener: bind");
                                continue;
                        }
                }
                break;
        }

        if (p == NULL) {
                fprintf(stderr, "listener: failed to bind socket\n");
                return 2;
        }

        freeaddrinfo(servinfo);

        printf("listener: waiting to recvfrom...\n");

        addr_len = sizeof their_addr;
        if ((numbytes = recvfrom(sockfd, buf, MAXBUFLEN-1 , 0,
                (struct sockaddr *)&their_addr, &addr_len)) == -1) {
                perror("recvfrom");
                exit(1);
        }

        printf("listener: got packet from %s\n",
                inet_ntop(their_addr.ss_family,
                        get_in_addr((struct sockaddr *)&their_addr),
                        s, sizeof s));
        printf("listener: packet is %d bytes long\n", numbytes);
        buf[numbytes] = '\0';
        printf("listener: packet contains \"%s\"\n", buf);

        close(sockfd);

        return 0;
}

最佳答案

在 linstener 中将套接字选项设置为 SO_REUSEPORT

SO_REUSEPORT - socket option allows multiple sockets on the same host to bind to the same port

关于linux - UDP 在同一台机器上广播?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21274622/

相关文章:

linux - 为什么 echo 显示命令本身而不是命令输出

linux - makefile 错误 *** 缺少分隔符。停止

c# - 我想使用 Remoting 还是只使用 Socket 连接

linux - Bluez-5.36 StartDiscovery() 方法

linux - 基本 bash 脚本 awk 和除法

windows - 在多宿主 Windows PC 上接收多播消息

c# - Linux .Net Core 接收传入的套接字

sockets - 是否为每个 UDP 连接打开一个新套接字?

c - 在C中,如何定期向多个对等点(可能是数千个)发送UDP数据报?

Windows BAT 或 CMD : send some data to a localhost udp port