我正在编写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进行广播的方法?
答案 0 :(得分:1)
使用connect()进行广播的问题是(除了修改send()/ write()的行为外),connect()将在套接字上安装一个过滤器,以便它只接收源 - IP字段匹配connect()参数中指定的IP地址。
这意味着如果您使用广播地址作为其参数调用套接字上的connect(),那么您的套接字将只接收来自该广播地址的数据包 - 但数据包永远不会(AFAIK)被标记为来自广播地址 - 而不是像往常一样将其Source-IP字段设置为发送数据包的计算机的IP地址。结果是,如果你将你的套接字连接到广播地址,你就不会在该套接字上收到任何数据包。