Unix域:connect():没有这样的文件或目录

xQu*_*are 8 c++ unix-socket

如标题中所述,我的connect()调用带有相应地址的unix域类型套接字导致错误ENOENT:没有这样的文件或目录.

两个套接字已正确初始化,并相应地创建和绑定套接字文件.服务器和客户端套接字在不同的进程中运行,但客户端进程是fork() - ed和execl() - ed.这也是我解析客户端和服务器套接字的地址,我用它来设置客户端套接字.服务器进程正在使用pthreads.

这是我的connect()尝试:

struct sockaddr_un address;
address.sun_family = AF_UNIX;
memcpy(address.sun_path, filepath.c_str(), filepath.length());
address.sun_path[filepath.length()] = '\0';

if(-1 == connect(this->unix_domain_descriptor_.descriptor(),       \
                (struct sockaddr*)&address,                       \
                size))
{
    global::ExitDebug(-1, "connect() failed", __FILE__, __LINE__);
    return -1;
}
Run Code Online (Sandbox Code Playgroud)

我尝试了不同的大小值,例如:

//  this is from unix(7) man page. It doesn't work neither with nor without "+1"
socklen_t size =  offsetof(struct sockaddr_un, sun_path);
          size += strlen(address.sun_path) + 1;
Run Code Online (Sandbox Code Playgroud)
//  this is from one of my books about linux programming
socklen_t size = sizeof(address);
Run Code Online (Sandbox Code Playgroud)
//  this is from a sample code which I found at the internet
socklen_t size = sizeof(address.sun_family) + strlen(address.sun_path);
Run Code Online (Sandbox Code Playgroud)
//  Update 1: 
socklen_t size = SUN_LEN(&address);
Run Code Online (Sandbox Code Playgroud)
//  this is what I tried out after looking into the declaration
//  of struct sockaddr_un
socklen_t size = strlen(address.sun_path);
Run Code Online (Sandbox Code Playgroud)

令人惊讶的是,除最后一个之外的所有初始化都会导致EINVAL:connect()的无效参数错误,我得到了ENOENT:没有这样的文件或目录只有最后一个.我甚至从互联网上尝试了整个例子,但没有成功.显然,使用size_t或int交换socklen_t 不会改变任何东西.

我已经检查了这个:

  • address.sun_path包含从根目录开始的正确套接字文件路径
  • address.sun_path的长度为61个字符
  • address.sun_family设置为AF_UNIX/AF_LOCAL
  • address.sun_family的大小为2个字节
  • 在创建和绑定两个套接字时没有错误
  • 服务器套接字处于侦听状态
  • sizeof(address)返回110,因为它应该是

现在我想知道为什么手册页示例不起作用以及是否有更改未在linux.die.netwww.kernel.org上更新.我的操作系统是Debian Squeeze,如果它是相关的.

我有什么想法我做错了吗?以及如何解决?如果您需要更多代码或有疑问,请不要犹豫问我(虽然我不需要说明这一点,但这是我在这里的第一篇文章>.<).

顺便说一句,抱歉我的英语不好

更新2

解决了.我将在下面的额外答案中将其发布为清晰度.

MvG*_*MvG 0

引用glibc 手册

\n\n
\n

您应该将本地命名空间中套接字地址的 LENGTH 参数计算为组件大小与文件名字符串的sun_family字符串长度(不是分配大小!)的总和。这可以使用宏来完成SUN_LEN

\n\n
    \n
  • 宏: int SUN_LEN (_struct sockaddr_un *_ PTR)
    \n 该宏计算本地命名空间中套接字地址的长度。
  • \n
\n
\n\n

下面的示例使用了您认为失败的计算:

\n\n
size = (offsetof (struct sockaddr_un, sun_path)\n       + strlen (name.sun_path) + 1);\n
Run Code Online (Sandbox Code Playgroud)\n\n

但你应该尝试一下这个宏。如果发生了变化,或者示例是错误的,那么该宏仍然很有可能按预期工作。如果是的话,你可以看看它的内部结构。乍一看,我觉得这个宏缺少+ 1所有示例中使用的部分。这与手册中的警告相匹配,使用 \xe2\x80\x9c而不是分配大小! \xe2\x80\x9d 正如你的帖子所说,如果没有这两者,这不起作用+ 1,但机会很小。

\n\n

出于好奇,路径的长度是多少?您是否检查过结构中提供的字段是否足够大以容纳它?sizeof(address.sun_path)您的实施中有哪些内容?我想知道您是否可能复制到未保留的内存,并且部分路径在下一个函数调用时被覆盖。

\n