Восстановление IP / порта из дескриптора сокета - PullRequest
6 голосов
/ 15 ноября 2010

Я пишу клон inetd , на котором я должен запустить сервер, который печатает IP-адрес и порт подключенного к нему клиента.

Когда я перезаписываю STDIN и STDOUT дескриптором сокета, мое первоначальное решение для этого было восстановить структуру sockaddr_in, которая содержит необходимую информацию. Однако выполнение этого с getsockname() возвращает пустую структуру со всеми битами, установленными на 0.

Есть идеи, что не так с моим подходом? Существуют ли другие способы восстановления IP / порта, которые я могу использовать?

Спасибо

Ответы [ 3 ]

9 голосов
/ 15 ноября 2010

Как указано R .., вы должны использовать 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);

См. Полный пример здесь .

3 голосов
/ 15 ноября 2010

Используйте 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});

Вы также должны проверять возвращаемое значение;если вы это сделаете, вы увидите, что он возвращает ошибки.

2 голосов
/ 15 ноября 2010

Если вам нужна эта информация для удаленного клиента, вы должны позвонить getpeername () .

...