您的位置:首页 > 其它

名字与地址转换函数笔记

2016-04-22 23:57 471 查看
《UNIX网络编程》第十一章笔记

1、客户、解析器和名字服务器的典型关系



/etc/resolv.conf通常包含本地名字服务器主机的IP地址

DNS服务一般使用UDP报文查询,如果答案太长,超出了UDP消息的承载能力,本地名字服务器和解析器自动切换到TCP

2、查找主机名所对应的IP地址最基本的函数是gethostbyname
<span style="font-size:14px;">#include <netdb.h>
struct hostent *gethostbyname(const char *hostname);

struct hostent {
char *h_name; //official name of host
char **h_aliases;// pointer to array of pointers to alias names
int h_addrtype;// host address type:AF_INET
int h_length; // length of address: 4
char **h_addr_list;// ptr to array of ptrs with IPV4 addrs
}
</span>

这个函数的局限是只能返回IPV4地址,而getaddrinfo函数能同时处理IPV4和IPV6地址。对代码中已有的gethostbyname不必做修改(除非整个因特网改为IPV6了),鼓励在新的程序中改用getaddrinfo函数。

当返回出错时,可通过调用hstrerror函数获取错误信息

<span style="font-size:14px;">extern int h_errno;
const char *hstrerror(int err);</span>


3、gethostbyaddr函数与gethostbyname相反,由一个二进制的IP地址找对对应的主机名

<span style="font-size:14px;">#include <netdb.h>
struct hostent *gethostbyaddr(const char *addr, socklen_t len, int family);</span>

参数addr是一个指向存放IPV4地址的某个in_addr结构的指针。

4、getservbyname用于根据给定的名字查找相应的服务。便于服务端口发生更改时,只需要修改下对应的服务端口配置文件(通常是/etc/services),而不需要重新修改编译应用程序。
<span style="font-size:14px;">#include <netdb.h>
struct servent *getservbyname(const char *servname, const char *protoname);

struct servent {
char *s_name;// official service name
char **s_aliases;// alias list
int  s_port; // port number, network byte order
char *s_proto;// protocol to use
}</span>
如某服务仅仅支持单个协议,则protoname可以置NULL。典型调用如下:
<span style="font-size:14px;">struct servent *sptr;
sptr = getservbyname("ftp", "tcp");
sptr = getservbyname("ftp", NULL);</span>


5、getservbyprot则是根据给定端口号和可选协议查找相应的服务
#inlcude <netdb.h>
struct servent *getservbyport(int port, const char *protoname);
port参数必须为网络字节序。典型调用如下:
<span style="font-size:14px;">struct servent *sptr;
sptr = getservbyport(hotns(21), "tcp");</span>


6、getaddrinfo支持ipv4和ipv6地址解析,能够处理名字到地址以及服务到端口这两种转换,返回的是一个sockaddr结构,可直接在套接字函数中使用。

<span style="font-size:14px;">#include <netdb.h>
int getaddrinfo(const char *hostname, const char *service,
const struct addinfo *hints, struct addrinfo **result);</span>
参数hostname是一个主机名或地址串(ipv4的点分十进制或ipv6的十六进制数串)

参数service是一个服务名或十进制端口号数串

参数hints可以是一个空指针,也可以是一个指向某个addrinfo结构的指针,用于填入期望返回的信息类型的暗示。

参数result指针参数返回一个指向addrinfo结构链表的指针。
<span style="font-size:14px;">struct addrinfo {
int ai_flags; // AI_PASSIVE, AI_CANONNAME
int ai_family; // AF_XXX
int ai_socktype; // SOCK_XXX
int ai_protocol; // 0 or ipproto_xxx for IPV4 and IPV6
socklen_t ai_addrlen; // length of ai_addr
char *ai_canonname; // ptr to canonical name for host
struct sockaddr *ai_addr; // ptr to socket address structure
struct addrinfo *ai_next; // ptr to next structure in linked list
}</span>常见使用场景:

1)、客户端程序指定hostname和service。
tcp客户在一个循环中对每个返回的ip地址,逐一调用socket和connect,直到有一个链接成功,或所有地址都尝试完为止。

udp客户由getaddrinfo填入的套接字地址结构用于调用sendto和connect。如判定第一个地址看来不工作,则尝试其余地址。

如清楚自己只处理某一类型的套接字,如ftp只处理tcp,则应吧hints结构的ai_socktype设置SOCK_STREAM

2)、服务端进程只指定service而不指定hostname,同时在hints结构中指定AI_PASSIVE标志。

gai_strerror根据getaddrinfo返回的非0错误值返回一个指向对应的出错信息的指针
<span style="font-size:14px;">#include <netdb.h>
const char *gai_strerror(int error);</span>

由于getaddrinfo返回的所有存储控件都是动态获取的,这些存储空间通过调用freeaddrinfo释放
<span style="font-size:14px;">#include <netdb.h>
void freeaddrinfo(struct addrinfo *ai);</span>


getaddrinfo函数及其行为和结果汇总



7、getnameinfo是getaddrinfo的互补函数,它以一个套接字地址为参数,返回描述其中的主机的一个字符串和描述其中的服务的另一个字符串
<span style="font-size:14px;">#include <netdb.h>
int getnameinfo(const struct sockaddr *sockaddr, socklen_t addrlen,
char *host, socklen_t hostlen,
char *serv, socklen_t servlen, int flags);</span>


8、上面讲解的函数,其中gethostbyname、gethostbyaddr、getservbyname、getservbyport这四个函数是不可重入的,可以更换使用带后缀_r的函数,或者使用getaddrinfo和getnameinfo函数。

四类网络相关信息截图



4000
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息