如何打印从的getaddrinfo IP地址() [英] How to print IP address from getaddrinfo()

查看:217
本文介绍了如何打印从的getaddrinfo IP地址()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在CentOS 6.4使用套接字用C

以下LIST1是我的code。

我的code命令行获取主机名和发送数据报给服务器成功UDP。

我想知道的是如何打印IP地址的getaddrinfo()室内用解析 192.168.10.1 格式

当我尝试打印IP地址分段错误发生。

有谁知道如何解决这个问题code?

 的#include<&stdio.h中GT;
#包括LT&;&string.h中GT;
#包括LT&;&unistd.h中GT;
#包括LT&; SYS / types.h中>
#包括LT&; SYS / socket.h中>
#包括LT&; netinet / in.h中>
#包括LT&;&netdb.h中GT;
#包括LT&;&errno.h中GT;INT
主(INT ARGC,CHAR *的argv []){
    INT袜子;
    结构addrinfo中的提示,*资源;
    INT N;
    INT犯错;
    如果(的argc!= 2){
        fprintf中(标准错误,用法:%s的DST \\ n,argv的[0]);
        返回1;
    }
    memset的(安培;提示,0,sizeof的(提示));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_DGRAM;
    ERR =的getaddrinfo(的argv [1],12345,&安培;提示,&安培; RES);
    如果(犯错!= 0){
        PERROR(的getaddrinfo);
        输出(的getaddrinfo%S \\ n字符串错误(错误));
        的printf(的getaddrinfo:%S \\ n,gai_strerror(ERR));
        返回1;
    }    袜子=插座(水库 - > ai_family,水库 - > ai_socktype,0);
    如果(袜子℃,){
        PERROR(插座);
        返回1;
    }
    {
        为const char * ipverstr;
        开关(水库 - > ai_family){
            案例AF_INET:
                ipverstr =的IPv4;
                打破;
            案例AF_INET6:
                ipverstr =IPv6的;
                打破;
            默认:
                ipverstr =未知;
                打破;
        }
        的printf(ipverstr =%S \\ n,ipverstr);
    }
    N = SENDTO(袜子,HELLO,5,0,水库 - > ai_addr,水库 - > ai_addrlen);
    // N = SENDTO(袜子,HELLO,5,0,(结构sockaddr *)地址,的sizeof(地址));
    如果(N。1){
        PERROR(SENDTO);
        {        }
        返回1;
    }
    结构SOCKADDR_IN *地址;
    地址=(结构SOCKADDR_IN *)的水库> ai_addr;
    的printf(INET_NTOA(in_addr等)罪=%S \\ n,INET_NTOA((struct in_addr,这个)addr-> sin_addr));    的printf(############完成!! ####### \\ n);
    关闭(袜子);
    freeaddrinfo(RES);
    返回0;
}


解决方案

在code偏出包括原型的 INET_NTOA()

编译器应该告诉你这一点。

不要添加:

 的#include< ARPA / inet.h>

然而,code编译仍然是由于对的 INET_NTOA() 假定返回 INT ,而它返回一个的char * 这是一个指针,它在64位系统上为8字节,这是不相同的大小为 INT 通常具有规模的 4 。由于这种不匹配的东西去可怕的错误,并在分段违例告终。


另请注意: INET_NTOA() 是用于仅IPv4地址。从 男人INET_NTOA逐字 (由我斜体字):


  

INET_NTOA()功能,在网络字节顺序鉴于互联网主机地址,转换为字符串中的的IPv4 的点分十进制格式。该字符串返回一个静态分配的缓冲区,随后的调用将
         覆盖



要能都转换(IPv4和IPv6)的二进制地址到结构sockaddr_XYZ 的char [] 使用 inet_ntop()

I’m trying to use socket in C on CentOS 6.4.

Following LIST1 is my code.

My code gets hostname from command line and sends datagram to server with UDP successfully.

What I want to know is how to print IP address that getaddrinfo() resolved wiht 192.168.10.1 format.

When I try to print IP address segmentation error happens.

Does anyone know how to fix this code?

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <errno.h>

int
main(int argc,char *argv[]){
    int sock;
    struct addrinfo hints,*res;
    int n;
    int err;
    if(argc != 2){
        fprintf(stderr,"Usage : %s dst \n",argv[0]);
        return 1;
    } 
    memset(&hints,0,sizeof(hints));
    hints.ai_family = AF_UNSPEC; 
    hints.ai_socktype = SOCK_DGRAM;
    err = getaddrinfo(argv[1],"12345",&hints,&res);
    if(err != 0){
        perror("getaddrinfo");
        printf("getaddrinfo %s\n",strerror(errno));
        printf("getaddrinfo : %s \n",gai_strerror(err));
        return 1;
    }

    sock = socket(res->ai_family,res->ai_socktype,0);
    if(sock < 0){
        perror("socket");
        return 1;
    }
    {
        const char *ipverstr;
        switch (res->ai_family){
            case AF_INET:
                ipverstr = "IPv4";
                break;
            case AF_INET6:
                ipverstr = "IPv6";
                break;
            default:
                ipverstr = "unknown";
                break;            
        }
        printf("ipverstr = %s\n ",ipverstr);            
    }
    n = sendto(sock,"HELLO",5,0,res->ai_addr,res->ai_addrlen);
    //n = sendto(sock,"HELLO", 5, 0,(struct sockaddr *)addr, sizeof(addr));
    if(n<1){
        perror("sendto");
        {

        }
        return 1;
    }
    struct sockaddr_in *addr;
    addr = (struct sockaddr_in *)res->ai_addr; 
    printf("inet_ntoa(in_addr)sin = %s\n",inet_ntoa((struct in_addr)addr->sin_addr));

    printf("############ finish !! #######\n");
    close(sock);
    freeaddrinfo(res);
    return 0;
}

解决方案

The code misses to include the prototype for inet_ntoa().

The compiler should have told you this.

Do add:

#include <arpa/inet.h>

However the code still compiles as due to the missing protoype for inet_ntoa() it is assumed to return int, whereas it returns a char* which is a pointer, which on a 64bit system is 8 bytes, which is not the same size as int which typically has a size of 4. Due to this mismatch things go terribly wrong and end up in a segmentation violation.


Also please note: inet_ntoa() is to be used for ipv4 addresses only. Verbatim from man inet_ntoa (italics by me):

The inet_ntoa() function converts the Internet host address in, given in network byte order, to a string in IPv4 dotted-decimal notation. The string is returned in a statically allocated buffer, which subsequent calls will overwrite


To be able to convert both (IPv4 and IPv6) struct sockaddr_XYZ's binary addresses to a char[] use inet_ntop().

这篇关于如何打印从的getaddrinfo IP地址()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆