繁体   English   中英

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

[英]Unix Domain : connect() : No such file or directory

如标题中所述,我对具有相应地址的unix域类型套接字的connect()调用导致错误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;
}

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

//  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;

//  this is from one of my books about linux programming
socklen_t size = sizeof(address);

//  this is from a sample code which I found at the internet
socklen_t size = sizeof(address.sun_family) + strlen(address.sun_path);

//  Update 1: 
socklen_t size = SUN_LEN(&address);

//  this is what I tried out after looking into the declaration
//  of struct sockaddr_un
socklen_t size = strlen(address.sun_path);

令人惊讶的是,除最后一个初始化外,所有初始化都导致EINVAL: connect()的 参数错误无效 ,而我得到ENOENT:仅最后一个没有此类文件或目录 我什至从互联网上尝试了所有示例,但没有成功。 显然,将socklen_t与size_t或int交换不会改变任何东西。

我已经检查过了:

  • 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

解决了。 为了清楚起见,我将其发布在下面的其他答案中。

在确定我可以正确处理套接字后,我对connect()的代码做了一些改动,现在可以正常工作了。 我只是在声明变量后添加了这一行:

memset(&address, 0, sizeof(struct sockaddr_un));

有谁知道为什么我需要将整个变量设置为0才能起作用? 我应该在一个新主题中提出这个问题还是在这里提出这个问题?

引用glibc手册

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

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

下面的示例使用一个计算,您认为该计算对您而言失败:

size = (offsetof (struct sockaddr_un, sun_path)
       + strlen (name.sun_path) + 1);

但是您应该尝试使用该宏。 如果更改了某些内容,或者该示例是错误的,则该宏仍然很有可能按预期运行。 如果是这样,您可以查看其内部。 乍一看,在我看来,该宏缺少所有示例中使用的+ 1部分。 与手册中的警告相匹配,使用“ 不是分配大小!”正如您的帖子所述,如果没有+ 1也不能使用,但是机会很小。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM