【发布时间】:2018-06-11 15:40:18
【问题描述】:
在这个最小的示例程序中读取发送 unix 数据报域套接字的地址时,我得到的地址长度为 0,但 unix 域套接字的手册页指定:
unnamed: 一个未绑定到路径名的流套接字使用 bind(2) 没有名字。同样,由 socket- 创建的两个套接字 pair(2) 未命名。当一个未命名套接字的地址是 返回,它的长度是 sizeof(sa_family_t),而 sun_path 不应该 被检查。
根据此手册页,我期望未命名套接字的地址长度为 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
}
【问题讨论】:
-
次要问题:
sizeof(PAYLOAD)应该是strlen(PAYLOAD)。你在那里得到指针的大小。否则,很好的问题。看起来像一个内核错误。如果行为符合预期,则手册页需要更新。如果您将SOCK_NAME设为像/tmp/socktest这样的真实路径,并在bind之前添加unlink,那么您将可以将某些东西移植到其他没有“抽象名称空间”的Unices。看看他们是否做同样的事情会很有趣。 -
has no name和sun_path should not be inspected有什么不清楚的地方?你为什么要给它写信? -
@stark 我正在写入将接收套接字绑定到抽象地址的路径
-
@WumpusQ.Wumbley 感谢您指出这一点,我在代码中创建了
PAYLOAD一个数组以使用正确的大小。我也尝试使用路径命名的套接字,地址在接收端的长度也为 0 -
@MaxBenson: sending 套接字未命名。接收者已经知道他们绑定的地址。
recvfrom()返回发件人地址,由于未命名,所以没有发件人地址。