设置和影响套接口选项的方法有
1.getsockopt和setsockopt
2.fcntl
3.ioctl
getsockopt和setsockopt
这两个方法仅适用于套接字
有两种基本类型的套接口选项:打开或关闭某个特性的二进制标志,取得并返回咱们能够设置或检验的特定值的选项,标有标志的列指明是否为标志选项,对于这些项,0表示关闭标志,非0表示打开标志。

并非全部的系统的套接字都支持全部的选项,必要时候自行验证一番。linux
套接字的不支持分为两种
1.未实现相关的定义,好比SO_REUSEPORT宏未定义
2.定义了名字,但并不支持,好比SO_REUSEPORT虽然定义,调用getsockopt却会报错。
针对这两种不支持的测试
1.#ifdef #else #endif
2.getsockopt返回失败或者取回的值为空。
套接口选项应该何时设置
抽取redis的一段代码来示例
//监听套接字接收accept事件的处理器
{
//accept的包裹函数
//设置socket的选项:设置非阻塞;禁用Nagle算法;设置keepalive
}
某些设置要更早一些,好比SO_RCVBUF和SO_SNDBUF,须要在服务器的监听套接口上设置,或者在未connect的客户端套接口上设置。
套接口基本选项
基本选项是协议无关的,但有些选项只能应用于特定类型的套接口中
SO_BROADCAST
此选项禁止或使能进程发送套接口广播的能力。只有数据报套接口支持广播,还必须是支持广播的网络。你不可能在一个点对点网络上发起广播。
SO_DEBUG
仅有TCP支持,当打开时,内核对TCP在此套接口上的发送和接收消息都作详细跟踪,这些信息保存在内核缓冲区,由程序trpt进行检查。
SO_ERROR
当套接口发生错误时,套接口名为so_error的变量被设置为标准的UNIX Exxx值的一个,它称为套接字的待处理错误。
内核能够经过select等多路复用I/O当即通知调用进程,进程能够经过SO_ERROR选项获取so_error的值,so_error随后由内核恢复为0.
当进程调用read且没有数据返回时,若是so_error为非0值,则read返回-1且errno设置为so_error的值,so_error随后复位为0.若是此套接口上有数据排队,则read返回那些数据,而不是返回错误条件。
若是在进程调用write时,so_error为非0值,则write返回-1值,而且errno设置为so_error的值,so_error也被复位为0.
SO_KEEPALIVE
给TCP一个保存存活选项之后,若是2个小时内此套接口的任何一方都没有数据交换。TCP就自动给对方发送一个保持存活探测分节,这是一个必须回复的TCP分节,它会致使如下三种状况:
1.对方回复一个正常的ACK,应用进程得不到任何通知(由于一切正常)。
2.对方以RST响应,它告诉本地TCP,对方已崩溃而且从新启动,套接口的待处理错误被设置成ECONNRESET,套接口自己被关闭。
3.对方对保持存活分节无任何响应,源自berkeley的TCP将发送另外8个分节,每隔75s一个,试图获得响应,若是对TCP的探测存活分节没有响应,套接口的错误被设置成ETIMEOUT,套接字自己被关闭。但若是收到某个ICMP的错误,则返回相应的错误。
主要是检测对方主机是否崩溃,若是对方进程崩溃,它的TCP将跨链接发送一个FIN,这能够经过多路复用检测到。
全部的TCP探测分节均无响应,也不意味这链接已中断,也有多是某个中间路由器暂时性的有问题,也就有可能关闭一个有效链接。
这个选项通常由服务器使用,由于若是客户主机崩溃,服务器将永远不知道,并继续等待不会到来的输入,这称为半打开链接,保持存活消息将检测这些链接并终止它们。
当TCP对端发生某些事件必须检测时的一些手段

SO_LINGER选项
只是函数close对面向链接的套接字如何操做,缺省设置是当即返回,若是有数据残留在套接口发送缓冲区,系统试着将这些数据发送给对端。
SO_LINGER可使咱们改变这些缺省操做。SO_LINGER的主要做用是去掉TIME_WAIT状态,使重启服务器进程是够从新绑定端口。做为替代,咱们能够在bind的时候使用SO_REUSERADDR选项。
SO_LINGER的另外一个做用是,告诉咱们发送的数据和FIN已由对方TCP确认,它并不能告诉咱们对方应用进程是否读取了数据,若是不设置该选项,咱们连对方是否接收了数据都不知道。
close的缺省操做,当即返回

设置了SO_LINGER,而且l_linger为正值时的closeredis

让客户知道服务器已读其数据的一个方法是:调用SHUT_WR的shutdown,并等待对方close链接的本地端。
使客户端知道服务器已读其数据的另外一个方式是:使用应用级的ACK。
SO_RCVBUF和SO_SNDBUF
每个套接口都有一个接收缓冲区和一个发送缓冲区
接收缓冲区被TCP和UDP用来保存收到的数据,一直保存到应用程序来读。对于TCP来讲,接收缓冲区的大小就是告知对方的窗口大小。TCP套接口接收缓冲区不可能溢出,由于对方不可能发出超出所通告窗口大小的数据,这就是TCP的流量控制。若是对方无视窗口大小而发出了超出窗口大小的数据,则接收方TCP将丢弃它。对于UDP来讲,若是接收到的数据装不进套接口缓冲区时,将会丢弃它。UDP是没有流量控制的,快的发送方能够轻易的淹没慢的接受者。
这致使接收方的UDP丢弃数据报。
当设置TCP套接字缓冲区大小时,函数调用顺序很是重要。TCP的窗口规模是在创建链接时用SYN交换来的,对于客户来讲,必须在connect以前设置,对于服务器来讲,意味着调用listen以前必须给监听套接字设置缓存区大小。给已链接的套接字设置该选项可能没有任何影响。
TCP套接字缓冲区的大小至少是MSS的三倍,而且必须是MSS的偶数倍,由于客户TCP必须为客户数据保存一份拷贝,直至接收到对端的确认。
fpathconf获取套接字缓冲区的上限。
SO_RCV_LOWAT和SO_SNDLOWAT
每一个套接口也都有一个发送低潮限度和一个接收低潮限度。
接收低潮限度是在多路复用API返回可读时,套接口接收缓冲区至少有的数据量。对于TCP和UDP,缺省值为1.
发送低潮限度是在多路复用API返回可写时,套接口发送缓冲区至少有的可用空间。对于TCP套接字,其值常缺省为2048.UDP没有发送缓冲区,只有发送缓冲区大小,对于UDP来讲,只要发送缓冲区大小大于套接口的低潮限度,UDP套接口就老是可写的。
SO_RCVTIMEO和SO_SNDTIMEO
给套接字设置一个接收和发送超时,缺省超时是禁止的。
接收超时影响:read、readv、recvfrom、recv和recvmsg
发送超时影响:write、writev、send、sendto和sendmsg。
SO_REUSEADDR和SO_REUSEPORT
SO_REUSEADDR一般为如下4个目的服务
1.SO_REUSEADDR容许启动一个监听服务器并绑定其众所周知端口,哪怕之前创建的将此端口用做本地端口的链接仍然存在。
2.SO_REUSERADDR容许在一个端口上启动同一个服务器的不一样实例,只要每一个实例绑定一个不一样的本地IP地址便可。
3.SO_REUSEADDR容许单个进程捆绑同一端口到多个套接字,只要每一个套接字捆绑不一样的本地IP端口。
4.SO_REUSEADDR还容许彻底重复的绑定,当一个IP和端口捆绑到一个套接字时,容许把同一个IP和端口捆绑到另外一个套接字。通常来讲,这个特性仅在支持多播的系统上才有,并且仅对UDP套接字(TCP不支持多播)。这个做用并非每一个系统都支持。
TCP套接口选项
TCP_KEEPALIVE
因为SO_KEEPALIVE的超时时间是2小时,而且难以修改,在linux上一般还会设置TCP_KEEPALIVE,设置TCP_KEEPALIVE仅在SO_KEEPALIVE套接口选项打开时才有效。
TCP_NODELAY
禁止TCP的nagle算法,缺省时,该功能是打开的。
Nagle算法:若是给定TCP链接上有待确认的分组,则直到现有数据被确认前,不往TCP上发送任何小分组。小分组即小于MSS的分组。若是可能,TCP老是发送最大大小的分组;Nagle算法的目的是防止TCP链接上有待确认的小分组存在。
Nagle算法常与另外一个TCP算法一块儿使用,延滞ACK算法,此算法致使在接收到数据时不当即发送ACK。而是由TCP等待一小段时间(50-200ms)才发出ACK,所但愿的是这段时间TCP有数据回复给对端,这样ACK能够捎带在这些数据上。又是就节省了一个TCP分节。
不适合Nagle和延滞ACK的客户端:以若干小数据分片发送单个逻辑请求给服务器的客户。对这类客户的修复办法是
1.使用writev合并小数据分片为完整的逻辑请求,而后发送
2.拷贝属于单个逻辑的多个小数据分片到一个缓冲区,而后完整发送
3.设置TCP_NODELAY并继续调用write两次。
fcntl函数算法
fcntl、ioctl和路由套接口操做小结
从表中来看,posix推荐使用fcntl