1 getsockopt和setsockopt函数
套接字选项粗分为两大基本类型:一是启用或禁止某个特性的二元选项,二是取得并返回特定值的选项,参数都是以指针形式传入的。
2 套接字状态
下面的套接字选项是从监听套接字继承来的:SO_DEBUF、SO_DONTROUTE、SO_KEEPALIVE、SO_LINGER、SO_OOBINLINE、SO_RCVBUF、SO_RCVLOWAT、SO_SNDBUF、SO_SNDLOWAT、TCP_MAXSEG和TCP_NODELAY。
3 通用套接字选项
3.1 SO_BROADCAST选项
只有数据报套接字支持广播。开启或禁止进程发送广播消息的能力。若禁止后发送广播消息会返回错误。
3.2 SO_ERROR选项
内核能以下列方式立即通知进程套接字错误:
1. 阻塞在对该套接字的select上。
2. 使用信号驱动I/O,产生SIGIO信号。
只能获取不能设置,获取后清零。
进程read但没有数据返回时,read返回-1并设置errno,有数据时返回数据,write时返回-1并设置errno。随后so_error都清零。
3.3 SO_KEEPALIVE选项
设置该选项后,如果2小时内该套接字的任一方向上都没有数据交换,TCP自动给对端发送一个探测分节,会导致以下三种情况之一:
1. 对端响应ACK,一切正常。
2. 对端响应RST,对端已崩溃且已重启,返回错误,关闭套接字。
3. 对端无响应,系统在重复发送多个分节后放弃,返回错误,关闭套接字。
修改这个时间可能会影响到主机上其它的进程。用select可检测到该错误。
本选项一般由服务器使用,不过客户也可使用。服务器也可以自行设置超时,用于清理客户,如关闭最近活动时间超过某个阈值的连接。
3.4 SO_LINGER选项
指定close面向连接的协议(TCP、SCTP)时如何操作。默认是立即返回,但试图发送缓冲区中的数据。
有三种情形:
1. 关闭本选项,采用默认设置。
2. close时丢弃数据,不推荐。
3. close时若有数据则睡眠,若阻塞则直到数据发送完或超过指定的时间才返回,若非阻塞则直接返回。
设置本选项后,close成功返回只表明数据和FIN已被对端TCP确认,不代表对端进程已读取数据。不设置的话,对端的确认都收不到。
可用shutdown后read来等待对方FIN(会在对端关闭后返回)。另一个方法是使用应用级确认,服务器接收数据后发送1字节的确认信息,客户在发送后等待这个确认。
3.5 SO_OOBINLINE选项
开启时带外数据将被留在正常的输入队列中,此时接收函数的MSG_OOB标志不能用来读带外数据。
3.6 SO_RCVBUF和SO_SNDBUF选项
设置SO_RCVBUF时要在connect或listen前。UDP没有流量控制,较小的接收缓冲区很容易被接收的数据淹没,导致新数据报被丢弃。
TCP缓冲区至少应该是相应连接的MSS值的四倍。依据是TCP快速恢复算法的工作机制,它使用3个重复的确认来检测分节丢失。
管道的容量称为带宽-延迟积,是带宽和RTT相乘,缓冲区小于这个值的话会降低性能。设置缓冲区大小时应该先获取当前系统默认值再判断是否要设置一个不同的值。
3.7 SO_RCVTIMEO和SO_SNDTIMEO选项
设置接收和发送的超时,设置为0表示禁止。默认是禁止。影响5个输入函数和5个输出函数。
3.8 SO_REUSEADDR和SO_REUSEPORT选项
SO_REUSEADDR选项有以下4个功用:
1. 允许监听套接字绑定一个已使用的端口,如在监听进程终止后又重启,此时派生出来的子进程还在为客户服务时。不指定的话bind会失败。所有TCP服务器都应指定本选项。
2. 允许在同一端口上启动同一服务器的多个实例,只要bind的本地IP不同即可。有些系统不允许对已绑定了通配地址的端口再绑定具体的IP。
3. 允许单个进程绑定同一端口到多个套接字上,只要IP不同。
4. 允许完全重复的绑定,一般仅支持UDP。
4 TCP套接字选项
4.1 TCP_MAXSEG选项
允许获取或设置最大分节大小MSS。并非所有系统上应用进程都可设置该选项。
4.2 TCP_NODELAY选项
开启将禁止TCP的Nagle算法。Nagle算法是指,如果连接上有数据待确认,后续待发送的小于MSS的分组就会被延迟,等待现有数据被确认,目的是减少WAN上小分组的数目。
对于小分组频繁的应用,如果WAN上的确认时间较长,会因此算法而感受到明显的延迟。
Nagle算法常与ACK延滞算法联合使用。该算法将对数据的确认ACK延滞一段时间发送,如果这段时间内自身有数据发送到对端,就可以捎带着ACK,省掉一个分节。
若服务器不立即回送数据,客户会因此产生延迟,此时需要启动TCP_NODELAY选项。
如果客户向服务器发送的数据是分多次发送的,发送完第一片后,因为数据未确认,客户的后面几片都会因Nagle算法而延迟,服务器因为没有接收到全部数据,不能立即回送数据,对第一片的确认因ACK延滞算法而延迟。此时有三种方法修正:
1. 用writev,一次发送多组数据。
2. 将所有数据复制到一个缓冲区中,再一次发送。
3. 用TCP_NODELAY,最不可取的方法。
5 fcntl函数
fcntl提供了与网络编程相关的如下特性:
1. 非阻塞I/O,设置O_NONBLOCK。
2. 信号驱动I/O,设置O_ASYNC。
3. F_SETOWN设置SIGIO和SIGURG信号的套接字属主(pid或gid)。