Getting IPV4 address from a sockaddr structure

后端 未结 6 1730
一整个雨季
一整个雨季 2020-12-07 22:32

How can I extract an IP address into a string? I can\'t find a reference that tells me how char sa_data[14] is encoded.

相关标签:
6条回答
  • 2020-12-07 22:43

    Emil's answer is correct, but it's my understanding that inet_ntoa is deprecated and that instead you should use inet_ntop. If you are using IPv4, cast your struct sockaddr to sockaddr_in. Your code will look something like this:

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

    Take a look at this great resource for more explanation, including how to do this for IPv6 addresses.

    0 讨论(0)
  • 2020-12-07 22:47

    inet_ntoa() works for IPv4; inet_ntop() works for both IPv4 and IPv6.

    Given an input struct sockaddr *res, here are two snippets of code (tested on macOS):

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

    Using inet_ntop()

    #include <arpa/inet.h>
    #include <stdlib.h>
    
    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);
    
    0 讨论(0)
  • 2020-12-07 22:55

    Just cast the entire sockaddr structure to a sockaddr_in. Then you can use:

    char *ip = inet_ntoa(their_addr.sin_addr)
    

    To retrieve the standard ip representation.

    0 讨论(0)
  • 2020-12-07 23:01

    You can use getnameinfo for Windows and for Linux.

    Assuming you have a good (i.e. it's members have appropriate values) sockaddr* called 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;
    }
    
    0 讨论(0)
  • 2020-12-07 23:06

    Once sockaddr cast to sockaddr_in, it becomes this:

    struct sockaddr_in {
        u_short     sin_family;
        u_short     sin_port;
        struct      in_addr sin_addr;
        char        sin_zero[8];
    };
    
    0 讨论(0)
  • 2020-12-07 23:06

    Type casting of sockaddr to sockaddr_in and retrieval of ipv4 using inet_ntoa

    char * ip = inet_ntoa(((struct sockaddr_in *)sockaddr)->sin_addr);
    
    0 讨论(0)
提交回复
热议问题