【问题标题】:Unix socket filename errorUnix 套接字文件名错误
【发布时间】:2016-08-28 06:16:34
【问题描述】:

这是我第一次使用 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 添加到代码顶部。

【问题讨论】:

    标签: c++ sockets unix c++14 unix-socket


    【解决方案1】:

    我们看一下bind的man page

    int bind(int sockfd, const struct sockaddr *addr,
                socklen_t addrlen);
    

    第三个参数是addrlen

    addrlen 指定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 没有优势。

    【讨论】:

    • 我认为这是问题所在!我是从手册页中直接做的,但是当我在这里查看beej.us/guide/bgipc/output/html/multipage/unixsock.html 时又回到了我的决定,作者似乎使用了我在上面的代码 sn-p 中使用的长度!
    • @Curious 我怀疑代码可能取决于平台特定的行为,并且可能在某些实现中很好地工作。我的建议解决了问题吗?
    • 是的!我有另一个问题,但我想我很快会问另一个问题。谢谢!
    • @Curious 无需怀疑作者所说的一切 :) 我确信他们是一名电缆专家。如果您不需要处理可移植性,很容易忽略结构填充。
    猜你喜欢
    • 2017-06-10
    • 1970-01-01
    • 2012-03-04
    • 2012-07-24
    • 1970-01-01
    • 1970-01-01
    • 2019-09-05
    • 1970-01-01
    • 2012-03-17
    相关资源
    最近更新 更多