域名和地址转换
2016-05-05 17:39
323 查看
在连接服务器的时候,我们不一定要指定服务器的IP地址,可以指定它的域名,因此就需要将域名转换为IP地址的函数。
1、通过getaddrinfo()函数
addrinfo;
在使用函数的过程中,自己根据自己的要求初始化一个addrinfo的结构体传进函数,并用一个addrinfo的指针去接受链表头指针,读取指针的ai_addr变量就可以得到解析后的IP地址。
该函数的使用过程中需要结合以下两个函数:
2、通过gethostbyname()函数
由于一个域名可能对应很多IP地址,因此保存解析后的IP地址是在一个二重指针h_addr_list中。
下面的例子显示了用法:
得到的是字符串指针,但该字符串指针实际指向的是 struct in_addr 结构体变量地址值。 (struct in_addr *)host‐>h_addr_list[i]
将字符串指针转换为 struct in_addr 结构体指针。 由于 inet_ntoa 参数类型是 struct in_addr 而不是 struct in_addr * ,所以用 * 运算符取出 struct
in_addr 结构体的值。
1、通过getaddrinfo()函数
#include<netdb.h> /** * hostname:要解析的主机域名或者IP * service:主机的端口 * hints:要返回的信息种类 * result:返回的一系列解析结果的链表 **/ int getaddrinfo( const char *hostname, const char *service, const struct addrinfo *hints, struct addrinfo **result ); 成功返回0,失败返回非0值要掌握这个函数需要了解一下struct
addrinfo;
struct addrinfo{ int ai_flags; //设置_PASSIVE表示可以接受任意地址或者端口 int ai_family; //地址族AF_INET(ipv4), AF_INET6(IPV6),AF_UNSPEC(任意的) int ai_socktype; //socket类型,SOCK_STREAM(TCP), SOCK_DGRAM(UDP) int ai_protocol; //默认0,或者IPPROTO_XXX socklen_t ai_addrlen; //ai_addr的长度 char *ai_canonname; // struct sockaddr *ai_addr; //socket address for socket struct addrinfo *ai_next; //链表中的下一个addrinfo节点 };
在使用函数的过程中,自己根据自己的要求初始化一个addrinfo的结构体传进函数,并用一个addrinfo的指针去接受链表头指针,读取指针的ai_addr变量就可以得到解析后的IP地址。
该函数的使用过程中需要结合以下两个函数:
1)void freeaddrinfo(struct addrinfo *addrList); 由于getaddrinfo()函数生成了链表,因此需要用这个函数对链表进行释放。 2)const char* gai_strerror(int arrorCode); 函数传进去getaddrinfo()失败时的数字,返回出错信息的字符串。以下的例子就是输入一个域名或者IP地址,最后打印IP地址的例子:
#include <sys/types.h> #include <sys/socket.h> #include <netdb.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> int main(int argc, char **argv) { if (argc != 2) { printf("Usag...\n"); exit(1); } struct addrinfo hints; struct addrinfo *res, *cur; int ret; struct sockaddr_in *addr; char ipbuf[16]; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_INET; /* Allow IPv4 */ hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */ hints.ai_protocol = 0; /* Any protocol */ hints.ai_socktype = SOCK_STREAM; ret = getaddrinfo(argv[1], NULL,&hints,&res); if (ret == -1) { perror("getaddrinfo"); exit(1); } for (cur = res; cur != NULL; cur = cur->ai_next) { addr = (struct sockaddr_in *)cur->ai_addr; printf("%s\n", inet_ntop(AF_INET, &addr->sin_addr, ipbuf, 16)); } freeaddrinfo(res); exit(0); }
2、通过gethostbyname()函数
#include <netdb.h> /** * hostname:需要解析的域名或者IP地址 * 返回hostent结构体指针 **/ struct hostent * gethostbyname(const char * hostname); struct hostent{ char * h_name; char ** h_aliases; char h_addrtype; char h_length; char ** h_addr_list; };
由于一个域名可能对应很多IP地址,因此保存解析后的IP地址是在一个二重指针h_addr_list中。
下面的例子显示了用法:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <arpa/inet.h> #include <netdb.h> int main(int argc, char *argv[]){ int i; struct hostent *host; if(argc < 2){ printf("Use : %s <hostname> \n", argv[0]); exit(1); } h ost = gethostbyname(argv[1]); for(i = 0; host‐>h_addr_list[i]; i++){ printf("IP addr %d : %s \n", i+1, inet_ntoa(*(struct in_addr *)host‐>h_addr_list[i])); } return 0; }上面代码中,打印IP地址是出现了令人困惑的类型转换。 host‐>h_addr_list[i]
得到的是字符串指针,但该字符串指针实际指向的是 struct in_addr 结构体变量地址值。 (struct in_addr *)host‐>h_addr_list[i]
将字符串指针转换为 struct in_addr 结构体指针。 由于 inet_ntoa 参数类型是 struct in_addr 而不是 struct in_addr * ,所以用 * 运算符取出 struct
in_addr 结构体的值。
相关文章推荐
- Lua下基本的网络编程示例
- linux网络编程用到的网络函数详解用和使用示例
- C#网络编程基础之进程和线程详解
- C++ 网络编程 总结
- Linux网络编程之UDP Socket程序示例
- Android网络编程之UDP通信模型实例
- 谈谈新手如何学习PHP网络编程第1/2页
- Python 网络编程起步(Socket发送消息)
- java必学必会之网络编程
- c# socket网络编程接收发送数据示例代码
- NodeJS学习笔记之网络编程
- Java网络编程之简单的服务端客户端应用实例
- java网络编程之识别示例 获取主机网络接口列表
- Python 网络编程说明第1/2页
- 详解Python Socket网络编程
- python网络编程学习笔记(一)
- python socket网络编程步骤详解(socket套接字使用)
- python网络编程之TCP通信实例和socketserver框架使用例子
- Android网络编程之获取网络上的Json数据实例
- Java网络编程基础教程之Socket入门实例