结构sockaddr_un:正确的初始化

时间:2012-08-04 15:01:56

标签: c++ c connect unix-socket

几天前,我遇到了与 struct sockaddr_un 相关的奇怪错误。有关详细信息,请参阅here

过了一段时间,我也找到了该错误的解决方案,这只是 memset 整个变量。现在我的问题是,就像那边的一篇文章中提出的那样,为什么?

为什么我需要将整个本地且非动态分配的变量设置为0,即使我已将每个成员设置为合法且正确的值?

在其他 struct 中(例如 struct sockaddr_in )是一个变量,用作填充,以便在内部看起来与 struct sockaddr相同即可。你必须填写(或者你可能没有?请纠正我)该变量为0,以使程序随时正确运行。

另外,在哪里可以查看connect()之类的源代码?可能是connect() - 函数没有整齐地实现?或者我错过了一些基础知识?

提前谢谢。

2 个答案:

答案 0 :(得分:1)

从阅读unix_stream_connect source code开始,似乎没有要求将结构归零。我编写了一个测试程序,它故意用一个值填充结构,客户端和服务器传递不同的填充值,并且它们能够很好地连接到彼此:

void init_addr (struct sockaddr_un *addr, const char *path, int I) {
    struct sockaddr_un tmp = { .sun_family = AF_UNIX };
    // fill sun_path
    memset(tmp.sun_path, I, UNIX_PATH_MAX);
    // copy path
    snprintf(tmp.sun_path, UNIX_PATH_MAX, "%s", path);
    *addr = tmp;
}

导致连接失败的原因是竞争条件,当客户端尝试connect时,服务器尚未完成设置。

答案 1 :(得分:0)

答案取决于几件事。

首先,如果你没有使用匿名名称(文件名不以0开头),那么你不需要清除结构。

如果您使用匿名名称,则取决于您是否将“len”参数传递给各种调用“sizeof(sockaddr_un)”或“len = strlen(local.sun_path + 1)+1 +” sizeof(local.sun_family);(这很难看,因为它忽略了可能的结构包装问题)。

对于匿名名称,套接字名称包括第一个0之后的所有字符,直到结构的末尾(由len定义)。因此,如果您将len作为sizeof(sockaddr_un)(建议使用)传递,则需要整个sun_path在两个调用之间进行匹配,因此需要将结构清零(或者相同地设置结构)。

为了获得最佳结果,可读性和可移植性,您应该使用len = sizeof(sockaddr_un),并在初始化之前将sockaddr_un memset为0。

这篇文章应该会有所帮助: Can not connect to Linux "abstract" unix socket