C unix 域套接字,recvfrom() 不设置 struct sockaddr* src_addr [英] C unix domain sockets, recvfrom() doesn't set struct sockaddr* src_addr

查看:36
本文介绍了C unix 域套接字,recvfrom() 不设置 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 后查看 cliaddrlen 时,问题就开始了.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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆