Linux 编程 之 【socket】 getaddrinfo
来源:互联网 发布:一对一视频聊天软件 编辑:程序博客网 时间:2024/06/07 16:42
【说明】
包含头文件:
#include<netdb.h>
函数原型:
int getaddrinfo( const char *hostname, const char *service, const struct addrinfo *hints, struct addrinfo **res );
参数说明:
hostname 一个主机名或者地址串(IPv4的点分十进制串或者IPv6的16进制串)
service 服务,即端口号,可以是一个服务的名称,比如"http", 也可以是一个数字字符串,比如“80”
hints 可以理解为约束条件,即你创建的,要获得的addrinfo结构,有什么约束,在hints中进行设置
res 这个就是我们最终获得的addrinfo结构
功能说明:
getaddrinfo 提供了将主机名和服务名转换成套接口地址结构(网络序)的功能
产生原因:
之前套接字编程,要得到sockaddr类型: 必须使用两种函数 getserverbyname(一类的函数 和 gethostent (一类的函数), 然后构建 sockaddr_in 结构,再强制类型转换得到 sockaddr结构。 而有了getaddrinfo这个函数后,直接调用就能得到sockaddr。
使用说明:
如果本函数返回成功,那么由res参数指向的变量已被填入一个指针,它指向的是由其中的ai_next成员串联起来的addrinfo结构链表。可以导致返回多个addrinfo结构的情形有以下两个:
1)如果与hostname参数关联的地址有多个,那么适用于所请求地址簇的每个地址都返回一个对应的结构。
当hints.ai_socktype=0,即未指定socket类型,则能会返回SOCK_DGRAM、SOCK_STREAM、SOCK_SEQPACKET等多种类型的addrinfo结构;
当指定hints.ai_socktype为SOCK_DGRAM或SOCK_STREAM时,则只会返回指定类型的addrinfo结构
例如,下面实例中hints.ai_socktype=SOCK_DGRAM,因此,for循环只能看到SOCK_DGRAM类型的addrinfo被获取。
2)如果service参数指定的服务支持多个套接口类型,那么每个套接口类型都可能返回一个对应的结构,具体取决于hints结构的ai_socktype成员。
参考:
http://www.cnblogs.com/chinacloud/archive/2011/08/11/2135141.html
http://www.cnblogs.com/lovell/archive/2010/09/19/1831233.html
server端代码与上篇相同
【代码示例 client】
/* udp client */ #include<stdio.h> #include<stdlib.h> #include<string.h> #include<errno.h> #include<sys/types.h> #include<sys/socket.h> #include<netinet/in.h> #include <netdb.h>#define SERVER_PORT 8888#define LOCAL_PORT 0#define BUFLEN 512 int main(int argc, char** argv){ int sockfd, rec_len, addrlen = sizeof(struct sockaddr); char recvbuf[BUFLEN] = {0}, sendbuf[BUFLEN] = {0}; struct sockaddr_in localaddr, rcvaddr, *psockin = NULL; struct addrinfo hints, *res = NULL, *pAddrInfo = NULL; const char *addr; char buf[INET_ADDRSTRLEN]; //server address memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = 0; hints.ai_flags = 0; if(0 != getaddrinfo("127.0.0.1", "8888", &hints, &res)) { printf("getaddriinfo error \r\n"); exit(1); } for (pAddrInfo = res; pAddrInfo != NULL; pAddrInfo = pAddrInfo->ai_next) { psockin = (struct sockaddr_in *)pAddrInfo->ai_addr; addr = inet_ntop(AF_INET, &psockin->sin_addr, buf, INET_ADDRSTRLEN); printf("### addrinfo[%d-%d-%d] addr = %s port = %d ###\r\n", pAddrInfo->ai_family, pAddrInfo->ai_socktype, pAddrInfo->ai_protocol, addr?addr:"unknow", ntohs(psockin->sin_port)); } if( (sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) < 0){ printf("Client create socket error(%d): %s \r\n", errno, strerror(errno)); exit(1); } //local address memset(&localaddr, 0, sizeof(localaddr)); localaddr.sin_family = AF_INET; localaddr.sin_addr.s_addr = htonl(INADDR_ANY); //内核分配IP localaddr.sin_port = htons(LOCAL_PORT); //内核分配端口,且不会冲突 if( bind(sockfd, (struct sockaddr*)&localaddr, sizeof(localaddr)) < 0){ perror("Client bind"); exit(1); } //main loop while(1) { printf("----- Client send to server: ----%d-%d-%d-%d-%x-%d-%d\n", SOCK_DGRAM, res->ai_family, res->ai_socktype, res->ai_protocol, ((struct sockaddr_in*)(res->ai_addr))->sin_addr.s_addr, ((struct sockaddr_in*)(res->ai_addr))->sin_port, res->ai_addrlen); fgets(sendbuf, BUFLEN, stdin); if( sendto(sockfd, sendbuf, strlen(sendbuf), 0, res->ai_addr,res->ai_addrlen) < 0) { perror("Client sendto"); exit(1); } if((rec_len = recvfrom(sockfd, recvbuf, BUFLEN, 0,(struct sockaddr *)&rcvaddr, &addrlen)) == -1) { perror("Client recvfrom"); exit(1); } if((((struct sockaddr_in*)(res->ai_addr))->sin_addr.s_addr != rcvaddr.sin_addr.s_addr) || (((struct sockaddr_in*)(res->ai_addr))->sin_port != rcvaddr.sin_port)) { printf("Client received data, but srcAddr isn't the server. \r\n"); memset(recvbuf, 0, sizeof(recvbuf)); continue; } recvbuf[rec_len] = '\0'; printf("Client received: %s From ip=%d port=%d \r\n", recvbuf, ntohl(rcvaddr.sin_addr.s_addr), ntohs(rcvaddr.sin_port)); memset(recvbuf, 0, BUFLEN);<span style="font-family: Arial, Helvetica, sans-serif;"></span> sleep(10); } close(sockfd); exit(0);}【执行】
root@linux-virtual-machine:/home/linux/01_Code/temp# ./udp-server &
[1] 3105
root@linux-virtual-machine:/home/linux/01_Code/temp#
======Server waiting for client's packets======
root@linux-virtual-machine:/home/linux/01_Code/temp# ./udp-client2
### addrinfo[2-2-17] addr = 127.0.0.1 port = 8888 ### /* 通过getaddrinfo函数获取的addrinfo信息 */
----- Client send to server: ----2-2-2-17-100007f-47138-16
fafafawegeatreatr
Server receive from client: fafafawegeatreatr
From ip=2130706433 port=54241
Client received: Hi,server has received packets!
From ip=2130706433 port=8888
----- Client send to server: ----2-2-2-17-100007f-47138-16
^C
0 0
- Linux 编程 之 【socket】 getaddrinfo
- linux c socket之GetAddrInfo
- linux socket编程客户端模型(用getaddrinfo)
- linux socket编程服务端模型(用getaddrinfo)
- socket编程之addrinfo结构体与getaddrinfo函数
- socket编程之addrinfo结构体与getaddrinfo函数
- socket编程之addrinfo结构体与getaddrinfo函数
- socket编程之addrinfo结构体与getaddrinfo函数
- socket编程之addrinfo结构体与getaddrinfo函数
- socket编程之addrinfo结构体与getaddrinfo函数
- socket编程之addrinfo结构体与getaddrinfo函数
- socket编程之addrinfo结构体与getaddrinfo函数
- socket编程之addrinfo结构体与getaddrinfo函数
- socket编程之addrinfo结构体与getaddrinfo函数
- socket编程之addrinfo结构体与getaddrinfo函数
- socket编程总结(一)getaddrinfo()函数详解
- Linux编程之socket
- linux编程之socket
- 第九周项目1-利用循环求和
- Ubuntu 或者win系统下svn更换用户名和密码
- C++ 11中关于Lambda表达式(匿名函数)
- LocalDate和Date的互换,以及LocalDate的使用
- _lame_close,referenced from错误
- Linux 编程 之 【socket】 getaddrinfo
- SQL Server用户自定义函数
- 30个让人兴奋的视差滚动(Parallax Scrolling)效果网站
- Java 1022
- 运行hadoop程序、java
- 2014年10月22日
- Threadlocal 1
- Java Arraylist应用
- MonkeyRunner在Windows下的Eclipse开发环境搭建步骤(兼解决网上Jython配置出错的问题)