2

几天前,我遇到了一个与struct sockaddr_un相关的奇怪错误。可以在此处阅读有关此内容的更多信息。

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

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

在其他struct(例如struct sockaddr_in)中是一个变量,它被用作填充,以便在内部看起来与struct sockaddr相同。您必须用 0 填充(或者也许您不必?请纠正我)该变量,以使程序在任何时候都能正确运行。

另外,我在哪里可以查看像 connect() 这样的源代码?会不会是 connect() 函数没有很好地实现?还是我缺少一些基础知识?

先感谢您。

4

2 回答 2

1

从阅读unix_stream_connect源代码来看,似乎不需要将结构归零。我编写了一个测试程序,故意用一个值填充结构,其中客户端和服务器传入不同的填充值,并且它们能够很好地相互连接:

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

于 2012-08-04T17:52:07.717 回答
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 设置为 0。

这篇文章应该会有所帮助: 无法连接到 Linux“抽象”unix 套接字

于 2013-04-13T14:19:27.073 回答