Подтвердить что ты не робот

Получение адреса IPV4 из структуры sockaddr

Как я могу извлечь IP-адрес в строку? Я не могу найти ссылку, которая сообщает мне, как char sa_data[14] закодирован.

4b9b3361

Ответ 1

Как только sockaddr отбрасывается на sockaddr_in, он становится следующим:

struct sockaddr_in {
    u_short     sin_family;
    u_short     sin_port;
    struct      in_addr sin_addr;
    char        sin_zero[8];
};

Ответ 2

Просто переместите всю структуру sockaddr в sockaddr_in. Затем вы можете использовать:

char *ip = inet_ntoa(their_addr.sin_addr)

Получить стандартное ip-представление.

Ответ 3

Ответ Эмиля правильный, но я понимаю, что inet_ntoa устарел, и вместо этого вы должны использовать inet_ntop. Если вы используете IPv4, добавьте struct sockaddr в sockaddr_in. Ваш код будет выглядеть примерно так:

struct addrinfo *res;   // populated elsewhere in your code
struct sockaddr_in *ipv4 = (struct sockaddr_in *)res->ai_addr;
char ipAddress[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &(ipv4->sin_addr), ipAddress, INET_ADDRSTRLEN);

printf("The IP address is: %s\n", ipAddress);

Взгляните на этот отличный ресурс для получения дополнительных пояснений, в том числе о том, как это сделать для IPv6-адресов.

Ответ 4

inet_ntoa() работает для IPv4; inet_ntop() работает как для IPv4, так и для IPv6.

Учитывая ввод struct sockaddr *res, вот два фрагмента кода:

Использование inet_ntoa()

struct sockaddr_in *addr_in = (struct sockaddr_in *)res;
char *s = inet_ntoa(addr_in->sin_addr);
printf("IP address: %s\n", s);

Использование inet_ntop()

char *s = NULL;
switch(res->sa_family) {
    case AF_INET: {
        struct sockaddr_in *addr_in = (struct sockaddr_in *)res;
        s = malloc(INET_ADDRSTRLEN);
        inet_ntop(AF_INET, &(addr_in->sin_addr), s, INET_ADDRSTRLEN);
        break;
    }
    case AF_INET6: {
        struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)res;
        s = malloc(INET6_ADDRSTRLEN);
        inet_ntop(AF_INET6, &(addr_in6->sin6_addr), s, INET6_ADDRSTRLEN);
        break;
    }
    default:
        break;
}
printf("IP address: %s\n", s);
free(s);

Ответ 5

Вы можете использовать getnameinfo для Windows и для Linux.

Предполагая, что у вас есть хороший (т.е. члены имеют соответствующие значения) sockaddr* называется pSockaddr:

char clienthost[NI_MAXHOST];  //The clienthost will hold the IP address.
char clientservice[NI_MAXSERV];
int theErrorCode = getnameinfo(pSockaddr, sizeof(*pSockaddr), clienthost, sizeof(clienthost), clientservice, sizeof(clientservice), NI_NUMERICHOST|NI_NUMERICSERV);

if( theErrorCode != 0 )
{
    //There was an error.
    cout << gai_strerror(e1) << endl;
}else{
    //Print the info.
    cout << "The ip address is = " << clienthost << endl;
    cout << "The clientservice = " << clientservice << endl;
}