Структура 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 сокету