使用 ::write 的 C++ UDP 广播

Posted

技术标签:

【中文标题】使用 ::write 的 C++ UDP 广播【英文标题】:C++ UDP Broadcast using ::write 【发布时间】:2018-05-30 15:20:51 【问题描述】:

我正在编写一个 UDP 客户端/服务器应用程序。服务器是广播服务器,它在特定端口上向同一子网上的两个客户端广播。每个客户端接收数据报并向服务器发送响应。每个客户端都事先知道服务器的ip地址。

我的客户端基本上和http://man7.org/linux/man-pages/man3/getaddrinfo.3.html 的客户端示例一样,即它使用connect() 函数来指定所有传出数据包的端点。通过使用连接的 UDP,客户端可以对套接字文件描述符使用 read() 和 write(),而不是 sendto/recvfrom。

对于我的服务器,我想采用类似的方法 - 配置用于广播的套接字,并在文件描述符上调用读/写。我可以 bind() 套接字来监听指定端口上的传入数据报,并且这些都被很好地收集。

减去错误检查,我的服务器代码如下所示:

int sockfd = socket(AF_INET, SOCK_DGRAM, 0);

int broadcast = 1;
setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof int);

struct sockaddr_in servaddr;
memset((char*) &servaddr, 0, sizeof servaddr);
servaddr.sin_family = AF_INET;
servaddr.sin_port   = htons(PORT);
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

int success = bind(sockfd, (struct sockaddr*) &servaddr, sizeof servaddr);

int BUFSIZE = 256;
char buf[BUFSIZE];

while (1)

    // this works fine
    int bytes_read = read(sockfd, buf, BUFSIZE);

    // WANT TO BROADCAST HERE
    int bytes_written = write(sockfd, buf, bytes_read); 

但是,当我尝试在 write() 行中广播数据包时,我收到“未指定目标地址”错误。我可以调用 connect() 来设置目标地址,但我认为 connect() 不适用于广播套接字。

有没有使用 write() 而不是 sendto 进行广播的方法?

【问题讨论】:

【参考方案1】:

使用 connect() 进行广播的问题在于(除了修改 send()/write() 的行为之外),connect() 将在套接字上安装一个过滤器,以便它只接收其来源- IP 字段与 connect() 的参数中指定的 IP 地址匹配。

这意味着如果您在套接字上调用 connect() 并使用广播地址作为其参数,那么您的套接字将只接收来自该广播地址的数据包——但数据包永远不会 (AFAIK) 标记为来自广播地址——更确切地说,它们的 Source-IP 字段设置为发送数据包的计算机的 IP 地址,就像往常一样。结果是,如果您将套接字连接()到广播地址,您将不会在该套接字上收到任何数据包。

【讨论】:

以上是关于使用 ::write 的 C++ UDP 广播的主要内容,如果未能解决你的问题,请参考以下文章

JavaCV音视频开发宝典:UDP广播推流 使用UDP方式推送广播TS流 实现UDP一对多广播

JavaCV音视频开发宝典:UDP广播推流 使用UDP方式推送广播TS流 实现UDP一对多广播

JavaCV音视频开发宝典:UDP广播推流 使用UDP方式推送广播TS流 实现UDP一对多广播

如何使用UDP进行跨网段广播

在本地测试 UDP 广播

Java笔记:UDP基础使用与广播