В C с программой сокетов я пытаюсь вставить getpeername () и getsockname в сокет server для печати IP-адреса сокета сервера и сокета клиента на стороне сервера. Примечание: мой серверный сокет использует INADDR_ANY. Я помещаю getpeername () и getsockname () в разные позиции:

1 / перед bind (): IP-адрес и клиентского, и серверного сокета - 0.0.0.0

2 / после bind (): снова IP-адрес клиентского и серверного сокетов 0.0.0.0

3 / после accept (): IP-адрес клиента - 10.0.2.15, а сокет сервера - по-прежнему 0.0.0.0.

Они правы? Вы можете объяснить, почему в этих случаях я получил 0.0.0.0 вместо конкретного адреса?

Примечание: на мой взгляд, я должен получить конкретный IP-адрес серверного сокета после bind (), потому что bind () уже привязывает серверный сокет к определенному IP-адресу. И после accept () я думаю, что и клиентский сокет, и серверный сокет тоже должны иметь конкретный IP-адрес, а не 0.0.0.0.

0
Vyolet 14 Окт 2018 в 22:54

1 ответ

Лучший ответ

Я не могу воспроизвести вашу проблему; например рассмотреть возможность

#include <unistd.h>
#include <netinet/ip.h>
#include <sys/socket.h>

int main(void)
{
    struct sockaddr_in  addr = {
        .sin_family = AF_INET,
        .sin_port   = 0,
        .sin_addr   = { INADDR_ANY },
    };

    int         fd;
    int         c_fd;
    struct sockaddr_in  p_addr;
    socklen_t       a_len = sizeof p_addr;

    fd = socket(AF_INET, SOCK_STREAM, 0);
    bind(fd, (void const *)&addr, sizeof addr);

    getpeername(fd, (void *)&p_addr, &a_len);
    getsockname(fd, (void *)&p_addr, &a_len);

    listen(fd, 10);
    c_fd = accept(fd, NULL, NULL);

    getpeername(c_fd, (void *)&p_addr, &a_len);
    getsockname(c_fd, (void *)&p_addr, &a_len);
}

Запуск его через strace и подключение к адресу привязки показывает

$ strace ./a.out
socket(AF_INET, SOCK_STREAM, IPPROTO_IP) = 3
bind(3, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
getpeername(3, 0x7ffdcf3af130, [16])    = -1 ENOTCONN (Transport endpoint is not connected)
getsockname(3, {sa_family=AF_INET, sin_port=htons(60093), sin_addr=inet_addr("0.0.0.0")}, [16]) = 0
listen(3, 10)                           = 0
accept(3, NULL, NULL)                   = 4
getpeername(4, {sa_family=AF_INET, sin_port=htons(35048), sin_addr=inet_addr("127.0.0.1")}, [16]) = 0
getsockname(4, {sa_family=AF_INET, sin_port=htons(60093), sin_addr=inet_addr("127.0.0.1")}, [16]) = 0

В ваших случаях 1 + 2 сервер отсутствует, и getpeername() завершится ошибкой с ENOTCONN.

Перед accept() getsockname возвращает 0.0.0.0, потому что вы слушаете INADDR_ANY.

Но после accept() getsockname() вернет локальный адрес.

0
ensc 14 Окт 2018 в 20:25