C unix 域套接字,recvfrom() 不设置 struct sockaddr* src_addr [英] C unix domain sockets, recvfrom() doesn't set struct sockaddr* src_addr
问题描述
我正在编写一个通过 unix 域套接字侦听 UDP 数据包的应用程序.考虑以下代码块.
I'm writing an application that listens for UDP packets over a unix domain socket. Consider the following code block.
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
的类型并不重要,我正在接收一个UDP 数据包并且client_message
包含我期望的所有数据.当我在调用 recvfrom
后查看 cliaddr
和 len
时,问题就开始了.cliaddr
不会像正常网络 TCP/UDP 那样被 recvfrom
修改,并且 len
在调用后设置为 0(这意味着 recvfrom没有向 &cliaddr
写入数据).我需要用 unix 域路径填充 cliaddr
中的信息,以便我可以发送响应.
Now the type of client_message
isn't really important, I'm receiving a UDP packet and client_message
contains all of the data I expect. The problem begins when I look at cliaddr
and len
after calling recvfrom
. cliaddr
is not modified by recvfrom
like it normally is with normal network TCP/UDP and len
is set to 0 after the call(which means recvfrom wrote no data to &cliaddr
). I need the information in cliaddr
to be populated with the unix domain path so I can send a response.
我做错了什么?
推荐答案
解决方案是在使用 Unix 域套接字时在客户端绑定套接字.否则为发送UDP数据包创建的临时路径名在sendto()
之后立即消失,这就解释了为什么客户端的地址信息在服务器端不可用.
The solution is binding the socket on the client side when using Unix domain sockets. Otherwise the transient pathname created for sending the UDP packet immediately disappears after sendto()
, which explains why the client's address information is not available on the server side.
请参阅 Stevens Network Programming page 419 或有关解决此问题的客户端实现示例:libpix.org/unp/unixdgcli01_8c_source.html
See Stevens Network Programming page 419 or see this for an example client implementation that solves this issue: 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 Network Programming 中常用)).同样,(SA *)
等价于 (struct sockaddr *)
.
Note: unp.h
defines Bind()
which is simply bind()
with some error checking(commonly used throughout Stevens Network Programming). In the same manner, (SA *)
is the equivalent to (struct sockaddr *)
.
这篇关于C unix 域套接字,recvfrom() 不设置 struct sockaddr* src_addr的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!