UDP在同一台机器上播放?

时间:2014-01-22 05:06:48

标签: linux sockets udp broadcast

我写了 broadcaster listener recvfrom 系统上的特定端口。我在 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;
}

2 个答案:

答案 0 :(得分:0)

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

  

SO_REUSEPORT - 套接字选项允许同一主机上的多个套接字绑定到同一端口

答案 1 :(得分:0)

在SYSFS中使用echo将5设为accept_local

1

这将允许本地通信。