Unix 套接字文件名错误
Unix socket filename error
这是我第一次使用 Unix 套接字编程,所以请原谅愚蠢的错误。我编写了以下函数来创建一个 unix 套接字。
int create_server_unix_socket(const string& socket_path) {
// STEP 1 : socket()
int unix_socket = socket(AF_UNIX, SOCK_STREAM, 0);
if (unix_socket == -1) {
throw std::runtime_error {"Error occured in socket() call : "s +
string(std::strerror(errno))};
}
// STEP 2 : bind(), setup the address structures for bind()
sockaddr_un local_address;
local_address.sun_family = AF_UNIX;
std::strcpy(local_address.sun_path, socket_path.c_str());
// unlink from before
unlink(socket_path.c_str());
// STEP 2 : bind()
size_t length = socket_path.size() + sizeof(local_address.sun_family);
if (::bind(unix_socket, reinterpret_cast<sockaddr*>(&local_address),
length) == -1) {
throw std::runtime_error {"Error occured in bind() call : "s +
string(strerror(errno))};
}
// STEP 3 : listen()
if (listen(unix_socket, 5) == -1) {
throw std::runtime_error {"Error occured in listen() call : "s +
string(strerror(errno))};
}
return unix_socket;
}
但是每当我尝试像这样创建套接字时
create_server_unix_socket("./unix_socket"s);
在当前工作目录中创建的文件是 unix_socke
而不是 unix_socket
,事实上,我尝试的任何名称都会发生这种情况。如果我尝试 unix_socket_longer_name
,生成的文件是 unix_socket_longer_nam
。我在 运行 Mac OS X(版本 10.11.4)上。
对我做错了什么有什么想法吗?另外,如果您发现我的代码中存在严重错误,请告诉我!我通过查阅手册页来写这篇文章,但我不完全确定我做对了。谢谢!
注意 :我正在用 C++14 编译它,您需要导入 std::literals::string_literals
命名空间才能使其工作。将 using namespace std::literals::string_literals
添加到代码的顶部。
我们来看看bind
的手册页
int bind(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
第三个参数是addrlen
addrlen
specifies the size, in bytes, of the address structure pointed to by addr
.
所以,您应该传递的是 sizeof local_address
。相反,您传递了 length
,即 socket_path.size() + sizeof(local_address.sun_family)
。这个大小几乎足够了,但是没有空终止符的空间,它忽略了 sockaddr_un
可能包含填充的可能性。
如果你真的想传递与路径匹配的长度而不是 local_address
的完整长度,你可以使用 offsetof
:
length = offsetof(sockaddr_un, sun_path) + socket_path.size() + 1;
但我看不出它比简单地传递 sizeof local_address
有什么优势。
这是我第一次使用 Unix 套接字编程,所以请原谅愚蠢的错误。我编写了以下函数来创建一个 unix 套接字。
int create_server_unix_socket(const string& socket_path) {
// STEP 1 : socket()
int unix_socket = socket(AF_UNIX, SOCK_STREAM, 0);
if (unix_socket == -1) {
throw std::runtime_error {"Error occured in socket() call : "s +
string(std::strerror(errno))};
}
// STEP 2 : bind(), setup the address structures for bind()
sockaddr_un local_address;
local_address.sun_family = AF_UNIX;
std::strcpy(local_address.sun_path, socket_path.c_str());
// unlink from before
unlink(socket_path.c_str());
// STEP 2 : bind()
size_t length = socket_path.size() + sizeof(local_address.sun_family);
if (::bind(unix_socket, reinterpret_cast<sockaddr*>(&local_address),
length) == -1) {
throw std::runtime_error {"Error occured in bind() call : "s +
string(strerror(errno))};
}
// STEP 3 : listen()
if (listen(unix_socket, 5) == -1) {
throw std::runtime_error {"Error occured in listen() call : "s +
string(strerror(errno))};
}
return unix_socket;
}
但是每当我尝试像这样创建套接字时
create_server_unix_socket("./unix_socket"s);
在当前工作目录中创建的文件是 unix_socke
而不是 unix_socket
,事实上,我尝试的任何名称都会发生这种情况。如果我尝试 unix_socket_longer_name
,生成的文件是 unix_socket_longer_nam
。我在 运行 Mac OS X(版本 10.11.4)上。
对我做错了什么有什么想法吗?另外,如果您发现我的代码中存在严重错误,请告诉我!我通过查阅手册页来写这篇文章,但我不完全确定我做对了。谢谢!
注意 :我正在用 C++14 编译它,您需要导入 std::literals::string_literals
命名空间才能使其工作。将 using namespace std::literals::string_literals
添加到代码的顶部。
我们来看看bind
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
第三个参数是addrlen
addrlen
specifies the size, in bytes, of the address structure pointed to byaddr
.
所以,您应该传递的是 sizeof local_address
。相反,您传递了 length
,即 socket_path.size() + sizeof(local_address.sun_family)
。这个大小几乎足够了,但是没有空终止符的空间,它忽略了 sockaddr_un
可能包含填充的可能性。
如果你真的想传递与路径匹配的长度而不是 local_address
的完整长度,你可以使用 offsetof
:
length = offsetof(sockaddr_un, sun_path) + socket_path.size() + 1;
但我看不出它比简单地传递 sizeof local_address
有什么优势。