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

标签 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 包含我期望的所有数据。当我在调用 recvfrom 后查看 cliaddrlen 时,问题就开始了。 cliaddr 没有被 recvfrom 修改,就像正常的网络 TCP/UDP 一样,len 在调用后设置为 0(这意味着 recvfrom没有数据写入&cliaddr)。我需要用 unix 域路径填充 cliaddr 中的信息,以便我可以发送响应。

我做错了什么?

最佳答案

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

参见 Stevens Network Programming 第 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 *)

关于C unix 域套接字,recvfrom() 不设置 struct sockaddr* src_addr,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26706584/

相关文章:

c - 获取对端IP地址和端口

带有私有(private) channel 的 Laravel Echo SocketIO

unix - ffmpeg 从子窗口捕获输出

linux - 为什么我的 Erlang 引导脚本可以在控制台运行,但在从 init 系统(sysvinit、upstart、systemd)运行时却不起作用?

c - 如何插值 HSV 颜色?

c - 在 C 中获取错误 "expected identifier or ' (' before ' {' token

c - Controller 之间的传输结构

c++ - 套接字发送调用被阻塞了这么久

c - gcc 4.4.3 下 C 代码中的奇怪行为

Unix tcsh - 使用命令行参数 $1 与\! :1