0
点赞
收藏
分享

微信扫一扫

TCP IP Socket In C, 2e - chapter 3 Of Names and Address Families


本文其实是在说DNS的东西,以及如何运行时判断使用IPv4还是IPv6。

chapter 3 Of Names and Address Families

  • ​​1. 名字和数字(IP地址)的映射​​
  • ​​2. 通用地址程序​​
  • ​​3. 从数字(IP地址)获取名字​​

1. 名字和数字(IP地址)的映射

人类记忆字符比记忆一串数字要更加在行,而且IP地址可能随着ISP的更改而在变化,所以使用一种称为“名字系统”(Name System)以完成名字和数字之间的映射就成了势在必行的东西。这便是DNS(Domain Name System)协议。

这里主要使用到3个函数。

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
struct addrinfo {
int ai_flags;
int ai_family;
int ai_socktype;
int ai_protocol;
socklen_t ai_addrlen;
struct sockaddr *ai_addr;
char *ai_canonname;
struct addrinfo *ai_next;
};

/*
* getaddrinfo():one or more addrinfo structures,这个是由双重指针results指向
* @params:
* hostStr: Internet host
* serviceStr: a service
* hints: specifies criteria, tells the system what kinds of endpoints the caller is interested in
* results:
* @return:
* 成功返回0
* 失败返回非0值
*
*/
int getaddrinfo(const char *hostStr, const char *serviceStr,
const struct addrinfo *hints, struct addrinfo **results);

/*
* freeaddrinfo(): 释放的是getaddrinfo返回的results参数所指向的。
* @params:
* addrList: 就是上一个的*results
* @return:
*/
void freeaddrinfo(struct addrinfo *addrList);

/*
* gai_strerror(): 把返回的int数字转为对应的错误信息
* @params:
* errorCode: 是getaddrinfo返回
* @return:
*/
const char *gai_strerror(int errorCode);

其中,​​getaddrinfo()​​函数第四个参数是一个二重指针,是一个链表形式的。因为对于一个域名来说,可能有多个IP地址或服务类型,如IPv4TCP、IPv6UDP,需要一一列举出来。

这里有一个使用上述函数的例子​​GetAddrInfo.c​​​,这个函数还使用了​​Practical.h​​​,​​DieWithMessage.c​​​以及​​AddressUtility.c​​​中的​​PrintSocketAddress()​​方法。编译的时候请注意。

2. 通用地址程序

Socket API允许我们把确定用IPv4还是IPv6地址的决定推迟到运行时来做。

最重要的其实是使用​​getaddrinfo()​​​传参​​hints​​​时,把​​ai_family​​​设置为​​AF_UNSPEC​​。这样就能够既接收IPv4又接收IPv6地址了。

这里使用到的程序是​​Practical.h​​​,​​TCPEchoClient.c​​​,​​TCPEchoServer.c​​​,​​TCPClientUtility.c​​​,​​TCPServerUtility.c​​​,​​DieWithMessage.c​​​,​​AddressUtility.c​​。

3. 从数字(IP地址)获取名字

其实这个是​​getaddrinfo()​​​的反着用,从IP地址得到对应的名字,不过使用的是函数​​getnameinfo()​​​,而且它的行为和​​getaddrinfo()​​​基本一致,返回值为0则成功,非0也可以传递给​​gai_strerror()​​以获取对应的错误信息。

/*
* getnameinfo: the inverse of getaddrinfo(3): it converts a socket address
* to a corresponding host and service, in a protocol-independent manner.
* 【通过socket地址同时获得以字符串表示的主机名和服务名】
* @params:
* addr: 地址
* addrlen: 地址长度
* host: 保存返回的主机名
* hostlen: 主机名长度
* serv: 保存返回的服务名
* servlen: 服务名长度
* flags:
* @return:
* 同getaddrinfo()
*/
int getnameinfo(const struct sockaddr *addr, socklen_t addrlen,
char *host, socklen_t hostlen,
char *serv, socklen_t servlen, int flags);

有关这些函数的详细内容,可以使用Man Pages查看,也可以参考​​Linux下C Socket编程基础API​​。尤其注意​​struct addrinfo​​​中​​ai_flags​​​的设置以及​​getnameinfo()​​​中的flags的设置,二者都可以使用位或操作符​​|​​。


举报

相关推荐

0 条评论