Что произойдет, если я вызову getpeername () и getsockname () на сокете сервера в разных местах? - PullRequest
0 голосов
/ 14 октября 2018

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

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

2 / после привязки (): Опять же, IP-адрес сокета клиента и сервера равен 0.0.0.0

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

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

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

1 Ответ

0 голосов
/ 14 октября 2018

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

#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 и подключение к bind-адресу показывает

$ 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() вернет местный адрес.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...