2013-11-21 71 views
3

我试图在CentOS 6.4上使用C中的套接字。如何从getaddrinfo()打印IP地址

以下LIST1是我的代码。

我的代码从命令行获取主机名,并成功向UDP发送数据报。

我想知道的是如何打印IP地址,其中getaddrinfo()的格式为192.168.10.1

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

有谁知道如何解决这段代码?

#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; 
} 

回答

4

该代码未包含原型inet_ntoa()

编译器应该告诉你这个。

不要添加:

#include <arpa/inet.h> 

但是代码仍然编译它被假定为由于缺少protoype为inet_ntoa()返回int,而它返回一个char*这是一个指针,它在64位系统上是8个字节,与int的大小不同,其大小通常为4。由于这种不匹配,事情发生严重错误,最终导致分段违规。


另请注意:inet_ntoa()只能用于ipv4地址。从man inet_ntoa(由我斜体)逐字:

INET_NTOA()函数是转换因特网主机,在网络字节顺序给出的IPv4点分十进制地址,为字符串。该字符串在一个静态分配的缓冲区,随后的调用将覆盖


为了能够既(IPv4和IPv6)struct sockaddr_XYZ的二进制地址转换为char[]使用inet_ntop()返回。

+0

我增加了它并获得了IP地址。 – user1345414

2

getaddrinfo()的对应部分是getnameinfo()。这将一个struct sockaddr变成一个字符串。