structure sockaddr_un:初始化正确

structure sockaddr_un: correct initialization

本文关键字:初始化 un sockaddr structure      更新时间:2023-10-16

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

过了一段时间,我也找到了这个错误的解决方案,只需对整个变量执行memset。现在我的问题是,正如已经在那一边的一篇帖子中提出的那样,为什么?

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

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

此外,在哪里可以查看类似connect()的源代码?会不会是connect()函数没有巧妙地实现?还是我错过了一些基础知识?

提前谢谢。

从阅读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时,服务器尚未完成设置。

答案取决于以下几点。

首先,如果您不使用匿名名称(文件名不是以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),并在初始化sockadd_un之前将其memset为0

这篇文章应该很有帮助:不能连接到Linux";摘要";unix套接字