从sockaddr结构获取IPV4地址

时间:2009-08-14 06:11:24

标签: c ip-address

如何将IP地址提取到字符串中?我找不到一个引用,告诉我char sa_data[14]是如何编码的。

7 个答案:

答案 0 :(得分:55)

只需将整个sockaddr结构投射到sockaddr_in即可。然后你可以使用:

char *ip = inet_ntoa(their_addr.sin_addr)

检索标准ip表示。

答案 1 :(得分:29)

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

答案 2 :(得分:28)

Emil的回答是正确的,但我的理解是{@ 1}}已被弃用,而您应该使用inet_ntoa。如果您使用的是IPv4,请将inet_ntop投射到struct sockaddr。您的代码将如下所示:

sockaddr_in

请查看this great resource以获取更多解释,包括如何为IPv6地址执行此操作。

答案 3 :(得分:24)

sockaddr投放到sockaddr_in后,就会变为:

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

答案 4 :(得分:3)

您可以使用getnameinfo for Windowsfor 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;
}

答案 5 :(得分:1)

以下程序解析给定的域:

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

可以在 here 中找到另一个示例。

答案 6 :(得分:0)

sockaddr强制转换为sockaddr_in,并使用inet_ntoa检索ipv4

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