我正在尝试在CentOS 6.4上使用C语言中的socket。
以下LIST1是我的代码。
我的代码从命令行获取主机名,并成功将数据报发送到服务器。
我想知道的是如何打印getaddrinfo()
解析192.168.10.1
格式的IP地址。
当我尝试打印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);
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;
}
答案 0 :(得分:7)
代码未包含inet_ntoa()
的原型。
编译器应该告诉你这个。
添加:
#include <arpa/inet.h>
然而代码仍然编译为由于inet_ntoa()
缺少原型而假定返回int
,而它返回char*
这是一个指针,在64位系统上是8个字节,与int
的大小不同,4
的大小通常为struct sockaddr_XYZ
。由于这种不匹配,事情变得极其错误并最终导致分段违规。
另请注意:inet_ntoa()
仅用于ipv4地址。来自man inet_ntoa
的逐字(我用斜体字):
inet_ntoa()函数将以网络字节顺序给出的Internet主机地址转换为 IPv4 点分十进制表示法中的字符串。该字符串在静态分配的缓冲区中返回,后续调用将进行 覆盖
能够将(IPv4和IPv6)char[]
的二进制地址转换为{{1}}使用inet_ntop()
。
答案 1 :(得分:3)
getaddrinfo()
的对应方为getnameinfo()
。这会将struct sockaddr
变成一个字符串。