C unix域套接字,recvfrom()没有设置struct sockaddr * src_addr

时间:2014-11-03 01:37:11

标签: c sockets unix udp unix-socket

我正在编写一个通过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的类型并不重要,我收到一个UDP数据包,client_message包含我期望的所有数据。在调用cliaddr后查看lenrecvfrom时,问题就开始了。 cliaddr不会像通常使用普通网络TCP / UDP那样修改recvfrom,并且在调用后len设置为0(这意味着recvfrom没有将数据写入&cliaddr )。我需要使用unix域路径填充cliaddr中的信息,以便我可以发送响应。

我做错了什么?

1 个答案:

答案 0 :(得分:7)

使用Unix域套接字时,解决方案是绑定客户端上的套接字。否则,在sendto()之后立即消失为发送UDP数据包而创建的瞬态路径名,这解释了为什么客户端的地址信息在服务器端不可用。

请参阅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(),带有一些错误检查(在整个史蒂文斯网络编程中常用)。以同样的方式,(SA *)相当于(struct sockaddr *)