Unix域:connect():没有这样的文件或目录
Unix Domain : connect() : No such file or directory
如标题所述,我对具有相应地址的unix域类型套接字的connect()调用导致错误ENOENT:没有这样的文件或目录。
这两个套接字被正确初始化,套接字文件被相应地创建和绑定。服务器和客户端套接字在不同的进程中运行,尽管客户端进程是fork()-ed和execl()-ed。这也是我解析客户端和服务器套接字地址的方式,我用它来设置客户端套接字。服务器进程正在使用pthreads。
这是我的连接()尝试:
struct sockaddr_un address;
address.sun_family = AF_UNIX;
memcpy(address.sun_path, filepath.c_str(), filepath.length());
address.sun_path[filepath.length()] = ' ';
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);
令人惊讶的是,除了最后一个初始化外,所有初始化都会导致connect()的EINVAL:无效参数错误,并且我得到了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.net或www.kernel.org上更新。如果相关的话,我的操作系统是Debian Squeeze。
你知道我做错了什么吗?如何解决?如果你需要更多的代码或有问题,请毫不犹豫地问我(尽管我可能不需要说明,但这是我在这里的第一篇文章>.<)
btw,很抱歉我的英语不好
更新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)
在您的实现中是什么?我想知道您是否正在复制到未保留的内存中,并且在下一次函数调用时会覆盖部分路径。
- .cpp和.h文件中的模板专用化声明
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- 文本文件中的单词链表
- CMake-按正确顺序将项目与C运行时对象文件链接
- 使用新行和不使用新行读取文件
- 在C++程序中输入的文本文件将不起作用,除非文本被复制和粘贴
- 挂起和取消挂起一个文件DLL
- 如何确定我已使用非编码文件到达 EOF?
- 命名空间中具有.h和.cpp文件的类
- 如何使用ndk-build.cmd构建Android.so文件
- 从包含m行的文件中提取n行,必要时(惰性地)重复该文件
- 读取文件并输入到矢量中
- 在C++中查找文件
- c++库的公共头文件中应该包含什么
- 用c++从输入文件中读取另一行
- Cppcheck生成xml转储文件
- 读取文件的最后一行并输入到链接列表时出错
- 无法编译 rtmidi 测试 cmidiin.cpp 文件, 非法指令
- 如何将内容数组写入文本文件?
- Unix域:connect():没有这样的文件或目录