【发布时间】:2014-02-12 00:29:40
【问题描述】:
我写了一个broadcaster和一个listener,它们recvfrom系统上的一个特定端口。我为 listener 中的套接字使用了 REUSEADDR 选项,以使 listener 的多个实例监视同一系统上的同一端口。
当我在不同的机器上运行 listener 并从另一台机器发送数据包时,所有的 listeners 都会收到数据包。但是当我在同一台机器上运行多个 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;
}
【问题讨论】:
-
您的发件人发送到哪个 IP 地址?如果它正在发送到 127.0.0.1,那么它正在发送单播数据包,并且只有一个侦听器会接收它们。如果它发送到您本地网络的广播地址(例如,如果您在 192.168.0.x 网络上,则为 192.168.0.255,或者如果您在 10.0.xy 网络上,则为 10.255.255.255,依此类推)然后所有侦听器应该会收到数据包。
-
我尝试发送到 255.255.255.255、localhost 和 0.0.0.0。在所有情况下,只有一个侦听器获取数据包。
-
试试你局域网的广播地址(基本上是你的 IP 地址按位或按位而不是你的网络掩码;例如对于 ip=192.168.2.5 netmask=255.255.255.0,broadcast_address=( 192.168.2.5 | 0.0.0.255) = 192.168.2.255
-
我现在也试过了。它没有用。我也尝试设置 SO_REUSEPORT 选项。但它似乎在 linux 中不可用; gcc 抛出编译错误
-
你能发布listner代码吗?
标签: linux sockets udp broadcast