###########################################################
DNS库函数的名字与地址转换
######################################################
通常给出的是数值地址(也就是IP地址),不方便记忆;
域名系统(DNS):用于在主机名字和IP地址之间的映射。
/etc/resolv.conf包含本地名字服务器主机的IP地址。
获取名字和地址信息的方法:
1.使用DNS
2.静态主机文件(/etc/hosts)
3.网络信息系统(NIS)
4.轻权目录访问协议(LDAP)
下面主要是在名字和数值之间转换的DNS函数:
#include <netdb.h>
#include <sys/socket.h>
#include <sys/types.h>
extern int h_errno
函数出错不设置errno,而是设置h_errno。
-----------------------------------------------------------
主机信息相关函数
/etc/hosts
根据IP地址和主机名 获取hostent信息
struct hostent
{
char*h_name; //host name
char*h_aliases; //alias names
inth_addrtype; //AF_INET
inth_length; //4
char**h_addr_list; //ipv4 address
};
struct hostent *gethostent(void); /* systemv/posix extension */
void sethostent(int stayopen);
struct hostent *gethostbyname(const char *hostname);
只能返回hostname对应的Ipv4的地址;ipv4的函数,一般不用了;
name一般是hostname,也可以是hostname对应的的IP。
struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type);
传入in_addr的机构指针和长度,type=AF_INET;返回hostname。
void herror(const char *s);
在stderr打印出错信息。
const char *hstrerror(int err);
传入h_errno,返回指向错误说明的字符串。
--------------------------------
以上函数是不可重入的,下面是相应的可重入版本:
由调用者分配空间,由可重入函数填写该结构。
不同的系统提供的接口不同。
int gethostent_r(struct hostent *ret, char *buf, size_t buflen, structhostent **result, int *h_errnop);
int gethostbyname_r(const char *hostname,
struct hostent *ret, 返回值存放的结构
char *buf, size_t buflen, 由调用者分配的空间和大小
struct hostent **result, //?
int *h_errnop);返回错误码
int gethostbyaddr_r(const void *addr, socklen_t len, int type,
struct hostent *ret,
char *buf, size_t buflen,
struct hostent **result,//?
int *h_errnop);返回错误码
void endhostent(void);
释放调用者创建的缓冲区
-----------------------------------------------------------
服务信息相关函数
/etc/services 包含从servname到port的映射关系
根据服务名和端口获取 servent信息
struct servent
{
char*s_name; /* service name */
char**s_aliases; /* alias name */
int s_port; /* port */
char*s_proto /* proto to use */
};
void setservent(int stayopen);
struct servent *getservent(void);
struct servent *getservbyname(const char *servname, const char *proto);
根据服务名超找相应的服务的信息。
典型调用:
sptr = getservbyname(“ftp”, “tcp”);
sptr = getservbyname(“telnet”, “tcp”);
sptr = getservbyname(“smtp”, “tcp”);
sptr = getservbyname(“git”, “tcp”);
struct servent *getservbyport(int port, const char *proto);
根据端口号超找相应服务的信息。
-------------------------
服务相关的函数的可重入版本:
int getservent_r(struct servent*result_buf, char *buf, size_t buflen, struct servent **result);
int getservbyname_r(const char*name, const char *proto, struct servent *result_buf, char *buf, size_t buflen,struct servent **result);
int getservbyport_r(int port,const char *proto, struct servent *result_buf, char *buf, size_t buflen, structservent **result);
void endservent(void);
释放调用者创建的缓冲区
-----------------------------------------------------
网络信息相关函数
/etc/networks
struct netent
{
char*n_name;//net work name
char**n_aliases;//alias names
intn_addrtype;//AF_INET
uint32_tn_net;//network number
};
struct netent *getnetent(void);
void setnetent(int stayopen);
struct netent *getnetbyname(const char *netname);
根据网络名称获取网络相关信息
struct netent *getnetbyaddr(uint32_t net, int type);
根据网络类型和网络号获取网络相关信息
---------------------------
网络相关的可重入的函数
int getnetent_r(struct netent *result_buf, char *buf, size_t buflen,struct netent **result, int *h_errnop);
int getnetentbyname_r(const char *name, struct netent *result_buf, char*buf, size_t buflen, struct netent **result, int *h_errnop);
int getnetbyaddr_r(uint32_t net, int type, struct netent *result_buf,char *buf, size_t buflen, struct netent **result, int *h_errnop);
void endnetent(void);
释放调用者创建的缓冲区
-----------------------------------------------------
协议信息相关函数
/etc/protocols
struct protoent
{
char*p_name;//protocol name
char**p_aliases;//alias name
intp_proto;//protocol number
};
struct protoent *getprotent(void);
void setprotoent(int stayopen);
struct protoent *getprotobyname(const char *protocolname);
根据协议名获取协议相关信息
struct protoent *getprotobynumber(int protonumber);
根据协议号获取协议相关信息
---------------------------
协议信息相关的可重入的函数
int getprotoent_r(struct protoent *result_buf, char *buf, size_tbuflen, struct protoent **result);
int getprotobyname_r(const char *name, struct protoent *result_buf,char *buf, size_t buflen, struct protoent **result);
int getprotobynumber_r(int proto, struct protoent *result_buf, char*buf, size_t buflen, struct protoent **result);
void endprotoent(void);
释放调用者创建的缓冲区
-----------------------------------------------------------
网络分组相关的函数
int setnetgrent(const char *netgroup);
int getnetgrent(char **host, char **user, char **domain);
可重入的版本:
int getnetgrent_r(char **host, char **user, char **domain, //主机名用户名域名
char *buf, int buflen //调用者创建空间和长度
);根据三个名字获取网络分组信息
void endnetgrent(void);
释放调用者创建的缓冲区
int innetgr(const char *netgroup, const char *host, const char *user,const char *domain);
检查成员hostname、username、domainname是否在netgroup网络分组中。
-----------------------------------------------------------
IPv6的协议函数
根据主机名、IP地址、服务名、端口号获取通用套接字地址结构。
struct addrinfo
{
int ai_flags;/AI_XXX
int ai_family;//AF_XXX
int ai_socktype;//SOCK_XXX
int ai_protocol;//0 orIPPROTO_XXX
socklen_t ai_addrlen;//length of ai_addr
char *ai_canonname;//hostname
struct sockaddr *ai_addr;//返回的通用套接字地址结构
struct addrinfo *ai_next;//结构链表的地址
}
ai_flags:
AI_PASSIVE
AI_CANONAME
AI_NUMERICHOST
AI_NUMERICSERV
AI_V4MAPPED:如果ai_family=AF_INET6,如果没有可用的AAAA记录,就返回A记录对应的ipv4映射的ipv6地址。
AI_ALL
AI_ADDRCONFIG
int getaddrinfo(const char*hostname,//主机名或IP地址
const char *service,//服务名或端口号
const struct addrinfo *hints,//用于设置addrinfo的前四个变量
struct addrinfo **res//返回的指向addrinfo结构链表的指针
);
const char *gai_strerror(interrcode);
根据getaddrinfo返回的非0的错误值res,返回一个指向出错信息串的指针。
void freeaddrinfo(structaddrinfo *res);
getaddrinfo返回的存储空间都是动态获取的。
ai指向getaddrinfo返回的第一个addrinfo结构,
调用freeaddrinfo将动态获取的空间返还给系统。
int getnameinfo(const struct sockaddr *sa, socklen_t salen, 套接字地址结构和长度
char *host, size_t hostlen, 主机名或IP及其长度
char *serv, size_t servlen, 服务名或端口号及其长度
int flags 标志
);
返回的主机名和服务名需要预先分配空间。
flags:
NI_DGRAM
NI_NAMEREQD
NI_NOFQDN
NI_NUMERICHOST
NI_NUMERICSCOPE
NI_NUMERICSERV
getaddrinfo和getnameinfo可重入的条件是由它调用的函数都是可重入的。
-----------------------------------------------------------
其它netdb函数:
例行返回一个远程命令的流:
int rcmd(char **ahost, int inport, const char *locuser, const char*remuser, const char *cmd, int *fd2p);
int rresvport(int *port);
int iruserok(uint32_t raddr, int superuser, const char *ruser, constchar *luser);
int ruserok(const char *rhost, int superuser, const char *ruser, constchar *luser);
原文地址:http://blog.csdn.net/wowotouweizi/article/details/43989031