几天前,我遇到了与 struct sockaddr_un 相关的奇怪错误。有关详细信息,请参阅here。
过了一段时间,我也找到了该错误的解决方案,这只是 memset 整个变量。现在我的问题是,就像那边的一篇文章中提出的那样,为什么?
为什么我需要将整个本地且非动态分配的变量设置为0,即使我已将每个成员设置为合法且正确的值?
在其他 struct 中(例如 struct sockaddr_in )是一个变量,用作填充,以便在内部看起来与 struct sockaddr相同即可。你必须填写(或者你可能没有?请纠正我)该变量为0,以使程序随时正确运行。
另外,在哪里可以查看connect()之类的源代码?可能是connect() - 函数没有整齐地实现?或者我错过了一些基础知识?
提前谢谢。
答案 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