【发布时间】:2016-01-09 09:37:41
【问题描述】:
我正在尝试使用 sendto() 函数通过 UDP 广播字符串。
以下代码在 Linux 机器(例如 Raspberry Pi)上运行良好,但在 iMac 和 MacBook Air 上的 OS/X 下失败。
#include <stdio.h>
#include <arpa/inet.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
int main(int argc, char*argv[])
{
const char *msg_str = "hello, world";
const char *bcast_addr = argv[1];
int port = atoi(argv[2]);
struct sockaddr_in sock_in;
int yes = 1;
int sinlen = sizeof(struct sockaddr_in);
memset(&sock_in, 0, sinlen);
int sock = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if ( sock < 0 ) {
printf("socket: %d %s\n", errno, strerror(errno));
exit(-1);
}
sock_in.sin_addr.s_addr=inet_addr(bcast_addr);
sock_in.sin_port = htons(port);
sock_in.sin_family = PF_INET;
if ( bind(sock, (struct sockaddr *)&sock_in, sinlen) < 0 ) {
printf("bind: %s %d %s\n", bcast_addr, errno, strerror(errno));
exit(-1);
}
if ( setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &yes, sizeof(int) ) < 0 ) {
printf("setsockopt: %d %s\n", errno, strerror(errno));
exit(-1);
}
if ( sendto(sock, msg_str, strlen(msg_str), 0, (struct sockaddr *)&sock_in, sinlen) < 0 ) {
printf("sendto: %d %s str='%s', sinlen=%d\n", errno, strerror(errno), msg_str, sinlen);
exit(-1);
}
printf("message sent!\n");
}
我的 OS/X 机器位于本地网络上,IP 地址为 192.168.0.4,广播地址为 192.168.0.255。 ifconfig en1 | grep broadcast 的输出产生以下内容:
inet 192.168.0.4 netmask 0xffffff00 broadcast 192.168.0.255
如果我像这样运行上面的代码:
a.out 192.168.0.255 1234
bind() 和 setsockopt() 函数有效,但 sendto() 返回 errno 49。我的程序打印以下内容:
sendto: 49 Can't assign requested address str='hello, world', sinlen=16
但如果我这样运行:
a.out 192.168.0.4 1234
然后一切正常。但当然广播只会发送到本地盒子。
当我在同一网络上的 Linux 机器上使用广播地址(例如 192.168.0.255)时,它工作正常。在我的 Mac 上,我尝试以普通用户和 root 用户身份运行,结果相同。我似乎记得这工作在几个版本的 OS/X 之前(我知道它在 Mavericks 上不起作用)。
知道苹果在这里做什么吗?
【问题讨论】: