获取和设置套接字的函数
getsockopt函数,setsockopt函数
原型:
extern int getsockopt (int __fd, int __level, int __optname,
void *__restrict __optval,
socklen_t *__restrict __optlen) __THROW;
extern int setsockopt (int __fd, int __level, int __optname,
const void *__optval, socklen_t __optlen) __THROW;
功能:设置和获取套接字选项
通用套接字选项:
SO_BROADCAST选项:开启或禁用进程广播的能力,注意TCP是不可能实现广播的,能够防止UDP应用在未申请广播时就开始广播
SO_DEBUG选项:仅有TCP支持,在内核中保留所有的跟踪信息
SO_ERROR选项:套接字上发生错误时通知,无法被设置只能被读取
SO_KEEPALIVE选项:再给一个TCP连接设置keep-alive之后,如果2小时连接没有活动事件发生那么发送保持存活探测分节,该分节必须被回应
若对端以RST回应,那么套接字的待处理错误将被置为ECONNRESER,套接字本身被关闭
若对方无回应,一种实现时将发送另外8个探测分节,11分15秒后没有回应则将放弃
SO_LINGER选项:给内核传递如下的struct
struct linger
{
int l_onoff; /* Nonzero to linger on close. */
int l_linger; /* Time to linger. */
};
若l_onooff选项为0,将关闭该选项,l_lingger选项将没有作用
选项为1,若l_linger为0,那么在close该socket时,将直接给对端发送一个RST,而不是传统的四次挥手关闭连接,避免time_wait状态(实际上time_wait是有益的,不该避免)
l_linger不为0,在close时,要么将缓冲区的数据全部发送完毕,要么等到l_lingger时间到才会close
但是linger实际上存在很多问题,比如对端崩溃将一直阻塞,并且linger时间是无法被精确设计的
解决方案如下:
SO_OBBINLINE选项
选项开启时,带外数据将留在正常的输入队列中
SO_RCVBUF和SO_SNDBUF选项
可以设置发送和接受缓冲区的大小,大小至少是MSS的4倍(快速恢复算法确定,对端发送三个重复ACK,需要保存,自己发送的也需要保存副本,共4个,若不能满足,那么将无法激活快速恢复算法),需要注意的是,该值应该在连接建立前就被设置好
SO_REVLOWAT和SO_SNDLOWAT选项
设置发送低水位和接受低水位的值(供select等调用),接受低水位的值默认为1,发送低水位的值默认为2048
SO_RCVTIMEO和SO_SNDTIMEO选项
允许给套接字的发送和接受设置一个超时值
SO_REUSEADDR选项
四个功能:(1)允许启动bind在一个已经连接上的端口上
(2)对于有多个别名IP的服务器不影响别名IP的bind,注意,对于TCP来说,完全相同的ip+port的绑定是一定不会成功的
(3)允许单个进程捆绑同一个端口到多个套接字上(IP必须不同)
(4)对于UDP允许完全重复的绑定
TCP套接字选项
TCP_MAXSEG选项
设置MSS
TCP_NODELAY选项
禁用Nagle算法,Nagle算法的目的是减少WAN上的小分组,但是小分组的延迟也会显著的增加(低于MSS的在确认前不发送)
然而对于以若干小片为主的程序却不应该开启TCP_NODELAY并且连续调用两次(有损网络),正确的做法是,使用writev一次发送,或者拼接到用户缓冲区后一次发送
fcntl函数
fcntl主要用于设置阻塞式与非阻塞式IO