Obtener la dirección IPV4 de una estructura sockaddr

5 minutos de lectura

Obtener la direccion IPV4 de una estructura sockaddr
Felipe Salazar

¿Cómo puedo extraer una dirección IP en una cadena? No puedo encontrar una referencia que me diga cómo char sa_data[14] está codificado.

Solo lanza todo sockaddr estructura a un calcetínaddr_in. Entonces puedes usar:

char *ip = inet_ntoa(their_addr.sin_addr)

Para recuperar la representación de ip estándar.

  • +1. Según la plataforma, recuerda comprobar primero la familia. Puede que no haya una dirección IPV4 para extraer…

    –Steve Jessop

    14 de agosto de 2009 a las 10:40

  • @SteveJessop ¿Cómo hacemos la verificación por cierto? ¿Hay algún código de ejemplo o algo que buscar?

    – Fatih Arslan

    13 de julio de 2012 a las 13:42

  • if (their_sockaddr_ptr->sa_family == AF_INET) { struct sockaddr_in *their_inaddr_ptr = (struct sockaddr_in *)their_sockaddr_ptr; } else { /* not an IPv4 address */ }o similar.

    –Steve Jessop

    13 de julio de 2012 a las 14:32


  • @Emil ¿Cómo conviertes toda la estructura sockaddr en sockaddr_in? Capaz de dar un ejemplo? 😀

    – señor

    27 de julio de 2012 a las 8:11


  • @mister Si tiene una pregunta, comience la pregunta, para eso está SO aquí. Las preguntas son ciudadanos de primera clase en SO. Y la respuesta es, ¡simplemente lánzalo! sockaddr es solo una dirección “abstracta”, ninguna dirección es realmente de ese tipo, solo define los campos comunes que deben tener todas las estructuras socketaddr. struct sockaddr * saddr = ...; if (saddr->sa_family == AF_INET) { struct sockaddr_in * saddr_in = (sockaddr_in *)saddr; ... }

    – Mecki

    10 de agosto de 2016 a las 10:35

Obtener la direccion IPV4 de una estructura sockaddr
jrc

inet_ntoa() funciona para IPv4; inet_ntop() funciona tanto para IPv4 como para IPv6.

Dada una entrada struct sockaddr *resaquí hay dos fragmentos de código (probados en macOS):

Usando inet_ntoa()

#include <arpa/inet.h>

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

Usando inet_ntop()

#include <arpa/inet.h>
#include <stdlib.h>

// obviously INET6_ADDRSTRLEN is expected to be larger
// than INET_ADDRSTRLEN, but this may be required in case
// if for some unexpected reason IPv6 is not supported, and
// INET6_ADDRSTRLEN is defined as 0
// but this is not very likely and I am aware of no cases of
// this in practice (editor)
char s[INET6_ADDRSTRLEN > INET_ADDRSTRLEN ? INET6_ADDRSTRLEN : INET_ADDRSTRLEN]
    = '\0';

switch(res->sa_family) {
    case AF_INET: {
        struct sockaddr_in *addr_in = (struct sockaddr_in *)res;

        ////char s[INET_ADDRSTRLEN] = '\0';
            // this is large enough to include terminating null

        inet_ntop(AF_INET, &(addr_in->sin_addr), s, INET_ADDRSTRLEN);
        break;
    }
    case AF_INET6: {
        struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)res;
        
        ////char s[INET6_ADDRSTRLEN] = '\0';
            // not sure if large enough to include terminating null?

        inet_ntop(AF_INET6, &(addr_in6->sin6_addr), s, INET6_ADDRSTRLEN);
        break;
    }
    default:
        break;
}
printf("IP address: %s\n", s);

  • en que encabezado

    – usuario1462586

    12 de junio de 2020 a las 7:02

  • #incluye

    – jrc

    18 de junio de 2020 a las 21:42

  • No estoy seguro de por qué está usando malloc y gratis aquí, un búfer estático sería la solución más apropiada.

    – Consultor independiente

    15 de mayo de 2021 a las 14:22

1647554767 482 Obtener la direccion IPV4 de una estructura sockaddr
Juan

La respuesta de Emil es correcta, pero tengo entendido que inet_ntoa está en desuso y que en su lugar deberías usar inet_ntop. Si está utilizando IPv4, emita su struct sockaddr para sockaddr_in. Su código se verá algo como esto:

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);

Echa un vistazo a este gran recurso para obtener más explicaciones, incluido cómo hacer esto para las direcciones IPv6.

1647554767 409 Obtener la direccion IPV4 de una estructura sockaddr
Ámbar

Una vez sockaddr lanzar a sockaddr_inse convierte en esto:

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

Puedes usar getnameinfo para ventanas y para Linux.

Suponiendo que tiene un bien (es decir, sus miembros tienen valores apropiados) sockaddr* llamado 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;
}

1647554768 907 Obtener la direccion IPV4 de una estructura sockaddr
x-yuri

El siguiente programa resuelve un dominio dado:

$ gcc a.c

$ ./a.out google.com
AF_INET: 216.58.214.238
AF_INET6: 2a00:1450:400d:803::200e

$ ./a.out google.com af_inet
AF_INET: 216.58.214.238

a.c:

#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>

int
main(int argc, char *argv[])
{
    struct addrinfo hints, *res, *cres;
    int r;
    char s[INET6_ADDRSTRLEN];

    memset(&hints, 0, sizeof(hints));
    if (argc > 2)
        hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_DGRAM;

    r = getaddrinfo(argv[1], NULL, &hints, &res);
    if (r) {
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(r));
        exit(EXIT_FAILURE);
    }

    for (cres = res; cres; cres = cres->ai_next) {
        switch (cres->ai_family) {
        case AF_INET:
            inet_ntop(AF_INET, &((struct sockaddr_in *)cres->ai_addr)->sin_addr, s, INET6_ADDRSTRLEN);
            printf("AF_INET: %s\n", s);
            break;
        case AF_INET6:
            inet_ntop(AF_INET6, &((struct sockaddr_in6 *)cres->ai_addr)->sin6_addr, s, INET6_ADDRSTRLEN);
            printf("AF_INET6: %s\n", s);
            break;
        }
    }

    freeaddrinfo(res);
}

Otro ejemplo se puede encontrar aquí.

1647554768 786 Obtener la direccion IPV4 de una estructura sockaddr
Aamir

Tipo de fundición de sockaddr para sockaddr_in y recuperación de ipv4 usando inet_ntoa

char * ip = inet_ntoa(((struct sockaddr_in *)sockaddr)->sin_addr);

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad