Восстановление IP/порт из дескриптора сокета

StackOverflow https://stackoverflow.com/questions/4186118

  •  10-10-2019
  •  | 
  •  

Вопрос

я пишу клон 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 ().

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top