Как получить IP-адрес принятого внутреннего сокета? - PullRequest
1 голос
/ 23 марта 2011

Мой вопрос:

Сервер создаст сокет, привязанный к данному порту и с адресом = INADDR_ANY.

listen () и accept () новое соединение. Затем мы можем получить ip-адрес клиента

от accept ().

Теперь я хочу узнать ip-адрес Сервера, так как хост сервера имеет

несколько сетевых карт на нем.

Как узнать ip-адрес сетевого интерфейса, с которого принят принятый внутренний сокет?

Я попробовал getockname, он дал мне номер порта, но ip все ноль.

Обновление: вот код:

Server.c (файлы заголовков удалены)

int main(void)
{

    struct sockaddr_in stSockAddr;
    int res, addr_len, SocketFD, ConnectFD;

    struct sockaddr_in addr;

    SocketFD = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);

    if(-1 == SocketFD)
    {
      perror("can not create socket");
      //exit(EXIT_FAILURE);
      return -1;
    }

    memset(&stSockAddr, 0, sizeof stSockAddr);
    stSockAddr.sin_family = AF_INET;
    stSockAddr.sin_port = htons(49335);
    stSockAddr.sin_addr.s_addr = INADDR_ANY;

    if(-1 == bind(SocketFD,(struct sockaddr *)&stSockAddr, sizeof stSockAddr))
    {
      perror("error bind failed");
      close(SocketFD);
     return -1;
    }


    printf("going to listen!\n"); 
    if(-1 == listen(SocketFD, 10))
    {   
      perror("error listen failed");
      close(SocketFD);
      //exit(EXIT_FAILURE);
      return -1; 
    }   

    ConnectFD = accept(SocketFD, NULL, NULL);

        if(0 > ConnectFD)
        {   
                perror("error accept failed");
                close(SocketFD);
                //exit(EXIT_FAILURE);
                return -1; 
        }   

    addr.sin_family = AF_INET;
    res = getsockname (ConnectFD, (struct sockaddr *)&addr, &addr_len);
    // if you remove the following comment, that means, if you call 
    // two times of getsockname, the result will be correct.
    //res = getsockname (ConnectFD, (struct sockaddr *)&addr, &addr_len);

    printf("addr:%x\n", addr.sin_addr.s_addr);

    while(1) {
        if (getchar() == 'q')
                        break;
    }

    close(ConnectFD);
    close(SocketFD);
    return 0;
}

Ниже client.c:

int main(void)
{

    struct sockaddr_in stSockAddr;

    int Res;

    int SocketFD = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);

    if (-1 == SocketFD)
    {
      perror("cannot create socket");
      exit(EXIT_FAILURE);
    }

    memset(&stSockAddr, 0, sizeof stSockAddr);

    stSockAddr.sin_family = AF_INET;
    stSockAddr.sin_port = htons(49335);
    Res = inet_pton(AF_INET, "192.168.1.102", &stSockAddr.sin_addr);

    if (0 > Res)
    {
      perror("error: first parameter is not a valid address family");
      close(SocketFD);
      exit(EXIT_FAILURE);
    }
    else if (0 == Res)
    {
      perror("char string (second parameter does not contain valid ipaddress");
      close(SocketFD);
      exit(EXIT_FAILURE);
    }

    if (-1 == connect(SocketFD, (struct sockaddr *)&stSockAddr, sizeof stSockAddr))
    {
      perror("connect failed");
      close(SocketFD);
      exit(EXIT_FAILURE);
    }

    /* perform read write operations ... */
    printf("client sockfd is successful\n"); 

      while(1) {

          if (getchar() == 'q')
              break;

      }


    shutdown(SocketFD, SHUT_RDWR);

    close(SocketFD);
    return 0;
}

Ответы [ 3 ]

9 голосов
/ 23 марта 2011

Используйте getsockname(2) для сокета, возвращенного из accept(2), , а не сокета, возвращенного из bind(2).

6 голосов
/ 29 декабря 2011

getsockname() получает имя переданного сокета. в этом примере вы передаете сокет, который создается принять функцию на сервере. этот сокет находится на стороне сервера, поэтому его имя и адрес относится к серверной части.

если вы хотите знать "кто со мной был связан" вы должны использовать getpeername() вместо getsockname.

удачи

1 голос
/ 08 марта 2013

если вы удалите следующий комментарий, это означает, что если вы позвоните Дважды полученного имени, результат будет правильным. res = getsockname (ConnectFD, (struct sockaddr *) & addr, & addr_len);

Вы должны инициировать addr_len.

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