structure sockaddr_un:初始化正确
structure sockaddr_un: correct initialization
几天前,我遇到了一个与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套接字
- 是否可以初始化不可复制类型的成员变量(或基类)
- C++使用整数的压缩数组初始化对象
- C++初始化基类
- 多成员Constexpr结构初始化
- 复制列表初始化的隐式转换的等级是多少
- 内联映射初始化的动态atexit析构函数崩溃
- 如何在C++中初始化嵌套类中的2个memeber
- 如何声明特征矩阵,然后通过嵌套循环初始化它
- 没有用于初始化C++中的变量模板的匹配构造函数
- 在未初始化映射的情况下,将值插入到映射的映射中
- C++成员初始化
- 为什么在C++中首先初始化成员类
- 同时具有"聚合初始化"和"模板推导"
- 初始化具有非默认构造函数的std::数组项的更好方法
- 是否可以在编译时初始化数组,以便在运行时不会花费时间?
- 我可以使用条件运算符初始化C风格的字符串文字吗
- 在C和C++中初始化结构中的数组
- 标准是否使用多余的大括号(例如 T{{{10}}})定义列表初始化?
- 在函数内部的声明中初始化数组,并在外部使用它
- 继承:构造函数,初始化C++11中基类的类C数组成员