Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 未命名的unix域套接字的地址长度错误_C_Linux - Fatal编程技术网

C 未命名的unix域套接字的地址长度错误

C 未命名的unix域套接字的地址长度错误,c,linux,C,Linux,在这个最小示例程序中读取发送unix数据报域套接字的地址时,我得到的地址长度为0,但unix域套接字的手册页指定: 未命名:未使用绑定到路径名的流套接字 绑定(2)没有名称。同样,套接字创建的两个套接字 对(2)未命名。当未命名套接字的地址为 返回时,其长度为sizeof(sau family),sun_路径不应为 接受检查 基于此手册页,我希望未命名套接字的地址长度为2。我是否误解了手册页,手册页是否不适用于类型为SOCK_DGRAM的unix套接字,或者我只是错误地读取了长度 #includ

在这个最小示例程序中读取发送unix数据报域套接字的地址时,我得到的地址长度为0,但unix域套接字的手册页指定:

未命名:未使用绑定到路径名的流套接字 绑定(2)没有名称。同样,套接字创建的两个套接字 对(2)未命名。当未命名套接字的地址为 返回时,其长度为sizeof(sau family),sun_路径不应为 接受检查

基于此手册页,我希望未命名套接字的地址长度为2。我是否误解了手册页,手册页是否不适用于类型为
SOCK_DGRAM
的unix套接字,或者我只是错误地读取了长度

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/un.h>

const char SOCK_NAME[] = { 0, 't', 'e', 's', 't' };
// or for pathnamed socket
// const char SOCK_NAME[] = "/tmp/test.uds";

const char PAYLOAD[] = "Hello!";

int main() {
    int rx_sock = socket(AF_UNIX, SOCK_DGRAM, 0);

    if (rx_sock < 0) {
        perror("Create RX");
        exit(1);
    }

    int tx_sock = socket(AF_UNIX, SOCK_DGRAM, 0);

    if (tx_sock < 0) {
        perror("Create TX");
        exit(1);
    }

    struct sockaddr_un bind_addr;
    bind_addr.sun_family = AF_UNIX;
    memcpy(bind_addr.sun_path, SOCK_NAME, sizeof(SOCK_NAME));

    socklen_t bind_len = sizeof(sa_family_t) + sizeof(SOCK_NAME);

    if (bind(rx_sock, (const struct sockaddr *)&bind_addr, bind_len) != 0) {
        perror("Bind RX");
        exit(1);
    }

    if (sendto(tx_sock, PAYLOAD, sizeof(PAYLOAD), 0, (const struct sockaddr *)&bind_addr, bind_len) < 0) {
        perror("Sendto");
        exit(1);
    }

    // For pathnamed socket
    // unlink(SOCK_NAME);

    struct sockaddr_un recv_addr;
    socklen_t recv_len = sizeof(recv_addr);
    char buffer[1024];

    ssize_t rx_count = recvfrom(rx_sock, buffer, sizeof(buffer), 0, (struct sockaddr *)&recv_addr, &recv_len);

    if (rx_count < 0) {
        perror("Recvfrom");
        exit(1);
    }

    printf("Address size of TX on receiver side: %d\n", recv_len); // 0

    recv_len = sizeof(recv_addr);

    if (getsockname(tx_sock, (struct sockaddr *)&recv_addr, &recv_len) != 0) {
        perror("getsockname");
        exit(1);
    }

    printf("Address size of TX on sender side: %d\n", recv_len); // 2
}
#包括
#包括
#包括
#包括
const char SOCK_NAME[]={0',t',e',s',t'};
//或用于名为socket的路径
//const char SOCK_NAME[]=“/tmp/test.uds”;
const char PAYLOAD[]=“你好!”;
int main(){
int rx_sock=socket(AF_UNIX,sock_DGRAM,0);
如果(rx_sock<0){
perror(“创建RX”);
出口(1);
}
int tx_sock=socket(AF_UNIX,sock_DGRAM,0);
如果(tx_sock<0){
perror(“创建TX”);
出口(1);
}
结构sockaddr\u unbind\u addr;
bind_addr.sun_family=AF_UNIX;
memcpy(bind_addr.sun_路径、SOCK_名称、sizeof(SOCK_名称));
socklen\u t bind\u len=sizeof(sau家族)+sizeof(SOCK\u名称);
if(绑定(rx_sock,(const struct sockaddr*)和绑定地址,绑定长度)!=0){
perror(“绑定RX”);
出口(1);
}
if(发送到(发送套接字,有效负载,大小(有效负载),0,(常量结构sockaddr*)和绑定地址,绑定长度)<0){
perror(“Sendto”);
出口(1);
}
//对于路径名套接字
//取消链接(袜子名称);
结构sockaddr\u un recv\u addr;
socklen_t recv_len=sizeof(recv_addr);
字符缓冲区[1024];
ssize_t rx_count=recvfrom(rx_sock,buffer,sizeof(buffer),0,(struct sockaddr*)和recv_addr,&recv_len);
如果(rx_计数<0){
perror(“Recvfrom”);
出口(1);
}
printf(“接收方发送的地址大小:%d\n”,recv_len);//0
recv_len=sizeof(recv_addr);
if(getsockname(tx_sock,(struct sockaddr*)&recv_addr,&recv_len)!=0){
perror(“getsockname”);
出口(1);
}
printf(“发送方发送的地址大小:%d\n”,recv_len);//2
}

当然,名称长度为零

char
数组中的第一个值是
0
,立即将字符串终止为零字节:

const char SOCK_NAME[] = { 0, 't', 'e', 's', 't' };
未命名:未使用bind(2)绑定到路径名的流套接字没有名称

不适用,因为您正在使用
bind()
绑定套接字:

您有一个未命名的未绑定Unix域数据报套接字
tx\u sock
,以及一个绑定到
bind\u路径中的抽象地址的Unix域数据报套接字
rx\u sock

注意:根据,未绑定的Unix域流套接字在Linux中未命名,其地址长度将为
sizeof(sa_family\u t)
。根据POSIX.1,所以我们确实需要小心我们对未绑定套接字地址及其长度的期望。在这种特殊情况下,在Linux中,使用手册页作为指南,未绑定的Unix域数据报套接字没有地址,因此其长度为零。(这甚至是有意义的:零地址长度表示您无法回复发件人。使用未绑定的流套接字,可以连接回发件人,但除了连接本身,没有其他方式回复发件人;这就是为什么在这种情况下,地址长度不为零,
sizeof(sa_family_t)

抽象Unix域套接字地址是Linux扩展;它们以NUL字节(
\0
)开头,在文件系统中不可见

您可以使用
sendto(tx\u sock,msg,msg\u len,0,bind\u path,bind\u path\u len)
发送消息

您使用
recvfrom(rx\u sock,buffer,sizeof buffer,0,&recv\u addr,&recv\u addrlen)
接收消息(使用
recv\u addrlen
正确初始化为
sizeof recv\u addr

由于
tx\u sock
未绑定到任何地址,因此未命名未绑定:它没有地址,无法回复,因此
recv\u addrlen==0

如果您添加代码将
tx\u sock
绑定到其他抽象地址,您将在
recv\u addr
recv\u addrlen
中收到该地址


(我用一个使用四个线程的测试程序验证了这一行为,其中每个线程向另一个线程发送一条消息,并打印所有接收到的消息以及它们的来源,包括标准地址和抽象地址。一切都按文档所述进行。)

小问题:
sizeof(有效负载)
应该是
strlen(有效载荷)
。你在那里得到了指针的大小。否则,这是一个很好的问题。这似乎是一个内核错误。如果行为符合预期,则手册页需要更新。如果你将
SOCK\u名称
设置为
/tmp/socktest
这样的真实路径,并在
绑定
之前添加了一个
取消链接
,那么你就拥有了一些可移植的东西到其他没有“抽象命名空间”的Unice。看看他们是否做了同样的事情会很有趣。
不清楚的地方没有名字
sun_path不应该被检查
?你为什么试图写入它?@stark我正在写入路径以将接收套接字绑定到摘要address@WumpusQ.Wumbley感谢您指出这一点,我制作了
PAYLOAD
代码中的数组使用了正确的大小。我还尝试使用名为socket的路径,该地址在接收端的长度也为0side@MaxBenson:发送套接字未命名。接收方已知道其绑定到的地址。
recvfrom()
返回发送方ad