APUE读书笔记-16网络通信(4)
(4)将地址和套接字进行关联
客户的套接字关联的地址并不是重点,我们可以让系统选择一个默认的地址。但是对于一个服务器,我们需要将一个公共的地址和服务器的套接字相关联,这样客户的请求将会到达。客户需要一个方式来发现这个地址,以便连接服务器,最简单的方式就是服务器保存一个地址并且将它注册到/etc/services中或者一个名字管理服务上。
我们使用bind函数来将一个地址和一个socket相互关联。
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr, socklen_t len);
返回值:如果成功返回0,如果错误,返回1。
对于我们能够使用的地址,有一些限制:
- 我们指定的地址必须对于进程所运行的机器来说是合法的:我们不能指定一个属于其他机器的地址。
- 地址必须和我们创建套接字时候使用的地址族的格式相匹配。
- 地址中的端口号码,不能小于1024,除非进程具有特殊的权限(也就是,超级用户权限)。
- 尽管有些协议支持多个绑定,一般来说也只有一个套接字端绑定到一个给定的地址上面。
对于因特网域,如果我们指定特殊的IP地址(INADDR_ANY),套接字端将会被绑定到系统所有的网络接口上面。这也就是说,我们可以接收任何来自安装到系统上面的网络接口卡上面的包。我们在后面将会看到,如果我们调用connect或者listen的时候没有将地址绑定到socket上面,那么系统将会选择一个地址,并且把它绑定到我们的套接字上。
我们可以使用getsockname函数来获取绑定到一个套接字上面的地址。
#include <sys/socket.h>
int getsockname(int sockfd, struct sockaddr *restrict addr, socklen_t *restrict alenp);
返回:如果成功返回0,如果错误返回1。
在调用getsockname之前,我们将alenp设置为指向一个整数,整数的内容包含sockaddr结构的缓存的大小。在返回的时候,整数被设置成返回的地址的大小。如果地址不适合提供的缓存,那么地址会被截断。如果当前没有地址绑定在套接字上面,那么结果是不确定的。
如果套接字被连接到了一个对等的节点上面,我们可以通过调用getpeername函数来获得对等节点的地址。
#include <sys/socket.h>
int getpeername(int sockfd, struct sockaddr *restrict addr, socklen_t *restrict alenp);
返回:如果成功返回0,如果错误返回1。
除了返回一个对等节点的地址之外,getpeername函数和getsockname函数都一样。
译者注
-
字节序
通过htonx,ntohx来确保。
-
地址
所有不同的地址结构都被强制转换成sockaddr数据结构并传递给socket函数。本文给出了ipv4和ipv6的地址。
-
地址表示
一般二进制用于机器,字符串用于人看。这里通过inet_pton, inet_ntop来做到。
-
地址查询
host, net, protocol, service均有get,set,end三类函数,以及各自的getbyname和getbynumber之类的函数,另外getaddrinfo和getnameinfo完成将host+service转换成地址信息,以及将地址信息转换成host+service(这里的地址信息包括了family,flag,以及套接字地址等)。
-
套接字绑定
可以bind一个套接字地址到套接字描述符,或者直接connect和listen让系统自己选。可以通过getsockname获取一个套接字描述符相关的地址,或者getpeername获取套接字对端的地址。