Ошибка имени файла сокета Unix

1

Это первый раз, когда я программирую с помощью 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).

Любые идеи о том, что я делаю неправильно? Также, если вы заметили что-то ужасное в моем коде, сообщите мне! Я написал это, посоветовавшись с страницами руководства, и я не совсем уверен, что сделал все правильно. Благодарю!

ПРИМЕЧАНИЕ. Я компилирую это с помощью С++ 14, вам нужно будет импортировать пространство имен std::literals::string_literals чтобы сделать эту работу. Добавьте using namespace std::literals::string_literals в начало вашего кода.

Теги:
c++14
sockets
unix-socket

1 ответ

2
Лучший ответ

Позвольте взглянуть на страницу man bind

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.

  • 0
    Я думал, что это проблема! Я сделал это прямо со страниц руководства, но вернулся к своему решению, когда посмотрел здесь beej.us/guide/bgipc/output/html/multipage/unixsock.html, и автор, похоже, использовал длину, которую я использовал в фрагменте кода выше!
  • 1
    @ Любопытно, я подозреваю, что код, вероятно, зависит от поведения платформы и может хорошо работать в некоторых реализациях. Мое предложение решило проблему?
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню