Структура sockaddr_un: правильная инициализация

Пару дней назад я столкнулся со странной ошибкой, связанной с struct sockaddr_un. Подробнее об этом можно прочитать здесь.

Через некоторое время я также нашел решение этой ошибки, которая просто записывала всю переменную. Теперь мой вопрос, как уже изложено в одном посте на этой стороне, почему?

Почему мне нужно установить целую локально, а не динамически размещаемую переменную в 0, даже если я установил для каждого члена допустимое и правильное значение?

В других структурах(например, struct sockaddr_in) - это переменная, которая используется в качестве отступа для того, чтобы внутренне выглядеть так же, как struct sockaddr. Вы должны заполнить (или, может быть, вам не нужно? Пожалуйста, исправьте меня) эту переменную с 0, чтобы программа работала правильно в любое время.

Кроме того, где я могу просмотреть исходный код, такой как connect()? Может ли быть так, что функция connect () не реализована аккуратно? Или я пропускаю некоторые основы?

Заранее спасибо.

2 ответа

Решение

Из чтения unix_stream_connectПохоже, что в исходном коде нет нужды обнулять структуру. Я написал тестовую программу, которая намеренно заполняет структуру значением, где клиент и сервер передают разные значения заполнения, и они могут нормально соединяться друг с другом:

void init_addr (struct sockaddr_un *addr, const char *path, int I) {
    struct sockaddr_un tmp = { .sun_family = AF_UNIX };
    // fill sun_path
    memset(tmp.sun_path, I, UNIX_PATH_MAX);
    // copy path
    snprintf(tmp.sun_path, UNIX_PATH_MAX, "%s", path);
    *addr = tmp;
}

Причиной сбоя соединения может быть состояние состязания, когда сервер еще не завершил настройку, когда клиент пытается connect,

Ответ зависит от нескольких вещей.

Во-первых, если вы не используете анонимные имена (имя файла не начинается с 0), вам не нужно очищать структуру.

Если вы используете анонимные имена, это зависит от того, передаете ли вы параметр "len" различным вызовам как "sizeof(sockaddr_un)" или как что-то вроде "len = strlen(local.sun_path+1) +1 + sizeof(local")..sun_family); (Это ужасно, потому что игнорирует возможные проблемы с упаковкой структуры).

Для анонимных имен имя сокета включает в себя все символы после первого 0 до конца структуры (как определено len). Поэтому, если вы передаете len в качестве sizeof (sockaddr_un) (что рекомендуется), вам потребуется весь sun_path для соответствия между двумя вызовами, и, следовательно, требуется обнуление структуры (или одинаковая установка структур).

Для достижения наилучших результатов, удобочитаемости и переносимости, вы должны использовать len = sizeof (sockaddr_un) и memset sockaddr_un в 0, прежде чем инициализировать его.

Этот пост должен быть полезен: не удается подключиться к "абстрактному" Linux Unix сокету

Другие вопросы по тегам