gpt4 book ai didi

sockets - Linux : Unix domain datagram sockets don't follow specification of connect/recv,吗?

转载 作者:行者123 更新时间:2023-12-03 12:00:56 24 4
gpt4 key购买 nike

connect的手册说:

If the socket sockfd is of type SOCK_DGRAM then addr is the address to which datagrams are sent by default, and the only address from which datagrams are received.



以下C程序似乎揭示了UNIX域套接字上Linux上 connect/ recv的实现错误,因为它从地址( @"PWE0")接收到了一条消息,而不是它所连接的消息( @"STAR"),并终止了该消息。与此相反,我期望的行为是程序不会终止,因为它忠实地等待来自其已连接地址的消息,该消息永远不会到达。 (我故意不使用返回值检查和打印语句来使示例困惑,因为可以使用 strace轻松检查它;在现实生活中,调用将由不同的进程进行。)
#include <sys/socket.h>

char header[] = "PLD ";

int main()
{
#define addrlen sizeof(unsigned short) + sizeof (char [1+4]) + sizeof(int)
int fd = socket(PF_UNIX, SOCK_DGRAM, 0);
bind(fd, &(struct sockaddr){ AF_UNIX, "\0PLD " }, addrlen);
int gd = socket(PF_UNIX, SOCK_DGRAM, 0);
bind(gd, &(struct sockaddr){ AF_UNIX, "\0STAR" }, addrlen);
int hd = socket(PF_UNIX, SOCK_DGRAM, 0);
bind(hd, &(struct sockaddr){ AF_UNIX, "\0PWE0" }, addrlen);
sendto(hd, "PWE0\0\0\0\n\1h\0\0\0\1\0\0\0\1", 18, 0,
&(struct sockaddr){ AF_UNIX, "\0PLD " }, addrlen);
connect(fd, &(struct sockaddr){ AF_UNIX, "\0STAR" }, addrlen);
char buf[32];
return recv(fd, buf, sizeof buf, 0);
}

那么,Linux [以及HP-UX(具有文件系统路径名)]是否违反了规范,还是我错过了某些东西?

最佳答案

编辑我注意到我的第一个答案是错误的。所以我编辑了很多文字。

EDIT2 固定addrlen,考虑到正在使用抽象地址空间。该代码的行为保持不变。

您对addrlen的定义有点莫名其妙。

  • 您似乎只为地址路径保留4 + 1个字节。我认为,“\0 | P | L | D ||\0”是6个字节。
  • sizeof(int)来自哪里?我不明白你是什么意思。

  • 但是,我认为sendto经历的原因是 sendto()connect()的顺序。如果将连接移到sendto之前,则会得到预期的行为。 Unix套接字缓冲数据报。发送的数据报在连接“开始过滤”之前经过。在交换connect和sendto的情况下,当操作系统(从发送者)接收到数据报时,可以看到该数据报已被过滤。当用户空间应用程序调用recv时,似乎不再进行过滤。
    Here is an strace output (last lines only) of the modified program.
    socket(PF_FILE, SOCK_DGRAM, 0) = 3
    bind(3, {sa_family=AF_FILE, path=@"PLD "}, 8) = 0
    socket(PF_FILE, SOCK_DGRAM, 0) = 4
    bind(4, {sa_family=AF_FILE, path=@"STAR"}, 8) = 0
    socket(PF_FILE, SOCK_DGRAM, 0) = 5
    bind(5, {sa_family=AF_FILE, path=@"PWE0"}, 8) = 0
    connect(3, {sa_family=AF_FILE, path=@"STAR"}, 8) = 0
    sendto(5, "PWE0\0\0\0\n\1h\0\0\0\1\0\0\0\1", 18, 0, {sa_family=AF_FILE, path=@"PLD "}, 8) = -1 EPERM (Operation not permitted)
    recvfrom(3, ^C <unfinished ...>

    我更改了在函数调用中定义地址的紧凑方式。这是我修改的代码:
    #include <sys/socket.h>
    #include <sys/un.h>
    int main()
    {
    const char hdr [] = "\0PLD ";
    socklen_t addrlen = sizeof(sa_family_t) + sizeof(hdr);

    int fd = socket(PF_UNIX, SOCK_DGRAM, 0);
    bind(fd, &(struct sockaddr){ AF_UNIX, "\0PLD " }, addrlen);
    int gd = socket(PF_UNIX, SOCK_DGRAM, 0);
    bind(gd, &(struct sockaddr){ AF_UNIX, "\0STAR" }, addrlen);
    int hd = socket(PF_UNIX, SOCK_DGRAM, 0);
    bind(hd, &(struct sockaddr){ AF_UNIX, "\0PWE0" }, addrlen);

    connect(fd, &(struct sockaddr){ AF_UNIX, "\0STAR" }, addrlen);
    sendto(hd, "PWE0\0\0\0\n\1h\0\0\0\1\0\0\0\1", 18, 0,
    &(struct sockaddr){ AF_UNIX, "\0PLD " }, addrlen);

    char buf[32];
    return recv(fd, buf, sizeof buf, 0);
    }

    我承认这有点莫名其妙。必须有一些与 addrlenbind()参数有关的未定义行为,因为如果我仅将原始代码addrlen更改为sizeof(struct sockaddr_un),我会得到不同的行为,其中connect()被拒绝,而recv块(也许是我的修改后的代码有一个我没有看到的错误)。

    关于sockets - Linux : Unix domain datagram sockets don't follow specification of connect/recv,吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16729807/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com