Восстановление IP/порт из дескриптора сокета
Вопрос
я пишу клон inetd в котором я должен запустить сервер, который печатает IP и порт клиента, подключающегося к нему.
Как я перезаписываю STDIN
а также STDOUT
с дескриптором сокета, мое первоначальное решение Чтобы сделать это, было восстановить sockaddr_in
Структура, которая содержит необходимую информацию. Делая это с getsockname()
, однако, возвращает пустую структуру со всеми битами, установленными в 0.
Есть идеи о том, что не так с моим подходом? Есть ли другие подходы, которые я могу использовать для восстановления IP/порта?
Спасибо
Решение
Как отметил, вы должны использовать getpeername
. Анкет Оба это функционируют и getsockname
Возьмите дескриптор файла в качестве первого аргумента, а не указатель потока (FILE *
) Использовать fileno(stdin)
Чтобы получить дескриптор файла для стандартного ввода (или жестко кодировать его STDIN_FILENO
, как это постоянно).
Кроме того, последний аргумент getsockname
а также getpeername
должен быть указатель на socklen_t
, не постоянная, и вы должны использовать sockaddr_in
Для TCP/IP:
struct sockaddr_in peeraddr;
socklen_t peeraddrlen = sizeof(peeraddr);
getpeername(STDIN_FILENO, &peeraddr, &peeraddrlen);
См. Полный пример здесь.
Другие советы
Использовать getpeername
. Анкет Я подозреваю, что ваша проблема в том, что getsockname
возвращает информацию для вашей собственной (локальной) стороны розетки, которая, вероятно, связана с 0,0.0.0 (то есть может принять подключения из любого интерфейса).
Редактировать: Я думаю, что я нашел вашу реальную ошибку, читая код. Эта строка неверна:
getsockname(stdin, &addr, sizeof(addr));
А getsockname
а также getpeername
функции принимают socklen_t *
(а указатель) как их третий аргумент, а не size_t
. Анкет Компилятор должен рассказать вам об этой ошибке, если вы не забыли включить заголовок с прототипом для getsockname
. Анкет Кроме того, как уже было сказано, stdin
это неверно. Пытаться:
socklen_t len = sizeof addr;
getpeername(0, &addr, &len);
или (только C99):
getpeername(0, &addr, (socklen_t[1]){sizeof addr});
Вы также должны проверять возвратное значение; Если бы вы это сделали, вы увидите, что это возвращает ошибки.
Если вам нужна эта информация для удаленного клиента, вам нужно позвонить getPeerName ().