我正在编写一个应用程序,通过unix域套接字来侦听UDP数据包。 考虑下面的代码块。
int sockfd; struct sockaddr_un servaddr; sockfd = socket(AF_LOCAL, SOCK_DGRAM, 0); if(sockfd < 0) { perror("socket() failed"); } unlink(port); bzero(&servaddr, sizeof(servaddr)); servaddr.sun_family = AF_LOCAL; strcpy(servaddr.sun_path, port); if(bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) { perror("bind() failed"); close(sockfd); } int n; struct sockaddr_un cliaddr; socklen_t len = sizeof(cliaddr); discovery_msgs client_message; bzero(&client_message, sizeof(client_message)); // Wait for a message to be received n = recvfrom(sock_fd, &client_message, sizeof(client_message), 0, (struct sockaddr *) &cliaddr, &len); // At this point n = 560, client_message is filled with the expected data //len = 0 and cliaddr has no information about the client that sent the data
现在, client_message
的types并不重要,我正在接收一个UDP数据包, client_message
包含了我所期望的所有数据。 调用recvfrom
后,我看cliaddr
和len
时,问题就开始了。 cliaddr
不会被recvfrom
修改,就像正常的networkingTCP / UDP一样,在调用之后len
被设置为0(意味着recvfrom没有写入数据到&cliaddr
)。 我需要cliaddr
的信息填充unix域path,以便我可以发送一个响应。
我究竟做错了什么?
当使用Unix域套接字时,解决方案是绑定客户端的套接字。 否则,为发送UDP数据包而创建的瞬时路径名在sendto()
之后立即消失,这就解释了为什么客户端的地址信息在服务器端不可用。
请参阅Stevens网络编程第419页,或者查看解决此问题的示例客户端实现:libpix.org/unp/unixdgcli01_8c_source.html
#include "unp.h" int main(int argc, char **argv) { int sockfd; struct sockaddr_un cliaddr, servaddr; sockfd = Socket(AF_LOCAL, SOCK_DGRAM, 0); bzero(&cliaddr, sizeof(cliaddr)); /* bind an address for us */ cliaddr.sun_family = AF_LOCAL; strcpy(cliaddr.sun_path, tmpnam(NULL)); Bind(sockfd, (SA *) &cliaddr, sizeof(cliaddr)); bzero(&servaddr, sizeof(servaddr)); /* fill in server's address */ servaddr.sun_family = AF_LOCAL; strcpy(servaddr.sun_path, UNIXDG_PATH); dg_cli(stdin, sockfd, (SA *) &servaddr, sizeof(servaddr)); exit(0); }
注意: unp.h
定义了Bind()
,它只是简单的bind()
并带有一些错误检查(通常在整个Stevens网络编程中使用)。 以相同的方式, (SA *)
等同于(struct sockaddr *)
。