1.1 概述
我们可以使用很多方法来获取和设置影响套接字的选项:
- getsockopt 和 setsockopt 函数;
- fcntl 函数;
- ioctl 函数。
我们会从介绍getsockopt 和 setsockopt 函数开始,然后介绍所有的套接字选项。我们按以下分类进行详细介绍:通用、IPv4、IPv6、TCP和SCTP。最后,我们还介绍fcntl函数,因为它是把套接字设置为非阻塞式I/O型或信号驱动式I/O型以及设置套接字属主的POSIX的方法。
1.2 getsockopt 和 setsockopt 函数
这两个函数仅用于套接字。
#include <sys/socket.h>
int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
均返回:若成功则为0,若出错则为-1
其中sockfd必须指向一个打开的套接字描述符,level(级别)指定系统中解释选项的代码或为通用套接字代码,或为某个特定于协议的代码(例如IPv4、IPv6、TCP或SCTP)。
optval是一个指向某个变量(*optval)的指针,setsockopt从 *optval中取得选项待设置的新值,getsockopt则把已获取的选项当前值存放到*optval中。*optval的大小由最后一个参数指定,它对于setsockopt是一个值参数,对于getsockopt是一个值-结果参数。
套接字选项粗分为两大基本类型:一是启用或禁止某个特性的二元选项(称为标志选项),二是取得并返回我们可以设置或检查的特定值得选项(称为值选项)。
1.3 套接字状态
对于某些套接字选项,针对套接字的状态,什么时候设置或获取选项有时序上的考虑。
下面的套接字 选项是由TCP已连接套接字从监听套接字继承来的SO_DEBUG、SO_DONTROUTE、SO_LINGER、SO_OOBINLINE、SO_RCVBUF、SO_RCVLOWAT、SO_SNDBUF、SO_SNDLOWAT、TCP_MAXSEG和TCP_NODELAY。这对TCP是很重要的因为accept一直要到TCP层完成三路握手后才会给服务器返回已连接套接字。如果想在三路握手完成时确保这些套接字选项中的某一个是给 已 连接套接字设置的,那么我们必须先给监听套接字设置该选项。
1.4 通用套接字选项
我们从通用套接字选项开始讨论、这些选项是协议无关的(也就是说,它们由内核中的协议无关代码处理,而不是由诸如IPv4之类特殊的协议模块处理),不过其中有些选项只能应用到某些特定类型的套接字中。举例来说,尽管SO_BROADCAST套接字选项是“通用”的,它却只能应用于数据报套接字。
1.4.1 SO_BROADCAST 套接字选项
本选项开启或禁止进程发送广播消息的能力。只有数据报套接字支持广播,并且还必须是在支持广播消息的网络上(例如以太网、令牌环网等)。我们不能再点对点链路上进行广播也不可能在基于连接的传输协议(例如TCP和SCTP)之上进行广播。
由于应用程序在发送广播数据报之前必须设置本套接字选项,因此它能够有效地防止一个进程在其应用程序根本没有设计成可广播时就发送广播数据报。
1.4.2 SO_DEBUG 套接字选项
本选项仅由TCP支持。当给一个TCP套接字开启本选项时,内核将为TCP在该套接字发送和接收的所有分组保留详细跟踪信息。这些信息保存在内核的某个环型缓冲区中,并可使用trpt程序进行检查。
1.4.3 SO_DONTROUTE 套接字选项
本选项规定外出的分组将绕过底层协议的正常路由机制。举例来说,在IPv4情况下外出分组将被定向到适当的本地接口,也就是由其目的地址的网络和子网部分确定的本地接口。如果这样的本地接口无法由目的地址确定(譬如说目的地主机不在一个点对点链路的另一端,也不在一个共享的网络上),那么返回ENETUNREACH错误。
路由守护进程(routed和gated)经常使用本选项来绕过路由表(路由表不正确的情况下),以强制将分组从特定接口送出。
1.4.4 SO_ERROR 套接字选项
当一个套接字上发生错误时,内核能够以下面两种方式之一立即通知进程这个错误。
- 如果进程阻塞在对该套接字的select调用上,那么无论是检查可读条件还是可写条件,select均返回并设置其中一个或所有两个条件。
- 如果进程使用信号驱动式I/O模型,那 就给进程或进程组产生一个SIGIO信号。
进程然后可以通过访问SO_ERROR套接字选项获取so_error的值。由getsockopt返回的整数值就是该套接字的待处理错误。so_error随后由内核复位为0。
这是我们遇到的第一个可以获取但不能设置的套接字选项。