#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);
- 对于TCP已连接套接字,下面的套接字选项须从监听套接字继承得到:
SO_DEBUG
、SO_DONTROUTE
、SO_KEEPALIVE
、SO_LINGER
、SO_OOBINLINE
、SO_RCVBUF
、SO_RCVLOWAT
、SO_SNDBUF
、SO_SNDLOWAT
、TCP_MAXSEG
、TCP_NODELAY
。
SO_BROADCAST
本选项开启或禁止进程发送广播消息的能力。只有数据报套接字支持广播,并且还必须是在支持广播消息的网络上(例如以太网、令牌环网等)。如果目的地址是一个广播地址且本套接字选项没有设置,那么返回EACCES
错误。
SO_ERROR
这是个可以获取但不能设置的套接字选项。当一个套接字上发生错误时,源自Berkeley的内核中的协议模块将该套接字的名为so_error
的变量设为标准的Unix Exxx值中的一个(pending error,待处理错误),内核可以通过”SIGIO
信号“或者”select
调用“立即通知进程这个错误,然后进程可以通过SO_ERROR
套接字选项获取so_error
的值。
SO_KEEPALIVE
本选项的功用是检测对端主机是否崩溃或变得不可达。我们必须明白内核通过socket的read/write将双方的连接异常通知到应用层的能力是有限的。假如A机器上的一个进程a正在和B机器上的进程b通信,当B机器的OS崩溃/主机断电/网络不可达时,a进程不会收到FIN包作为连接终止的提示。此时对于a进程有如下情况:
-如果a进程阻塞在read上,那么结果只能是永远的等待。
-如果a进程先write然后阻塞在read,由于收不到B机器TCP/IP栈的ack,TCP会持续重传,然后在阻塞的read调用上返回错误:
ETIMEDOUT/EHOSTUNREACH/ENETUNREACH。假如B机器恰好在某个时候恢复和A机器的通路,并收到a某个重传的pack,
因为不能识别所以会返回一个RST,此时a进程上阻塞的read调用会返回错误ECONNREST。
给一个TCP套接字设置存活SO_KEEPALIVE
选项后,如果2小时内(大多数内核基于整个内核维护该时间参数,而不是基于套接字的)在该套接字的任一方向上都没有数据交换,TCP就自动给对端发送一个保持存活探测分节(keep-alive probe)。
SO_RCVBUF和SO_SNDBUF
每个套接字都有一个发送缓冲区和一个接收缓冲区,这两个套接字选项允许我们改变这两个缓冲区的默认大小。对于TCP来说,套接字接收缓冲区不可能溢出,因为不允许对端发出超过本端所通告窗口大小的数据,这就是TCP的流量控制。对于UDP来说,由于没有流量控制,较快的发送端可以很容易地淹没较慢的接收端,导致接收端的UDP丢弃数据报。
当设置TCP套接字接收缓冲区的大小时,函数调用顺序很重要,这是因为TCP的窗口规模选项是在建立连接时用SYN分节与对端互换得到的。
对于客户,这意味着SO_RCVBUF选项必须在调用connect之前设置;
对于服务器,这意味着SO_RCVBUF选项必须在调用listen之前给监听套接字设置。
SO_RCVLOWAT和SO_SNDLOWAT
每个套接字还有一个接收低水位标记和一个发送低水位标记,它们由select函数使用。这两个套接字选项允许我们修改这两个低水位标记。
-接收低水位标记是让select返回“可读”时套接字接收缓冲区中所需的数据量。对于TCP和UDP,其默认值为1。
-发送低水位标记是让select返回“可写”时套接字发送缓冲区中所需的可用空间。对于TCP,其默认值为