TCP Socket选项

SO_KEEPALIVE(参考SO_KEEPALIVE)

socket保活选项。

设置该选项后,服务器在保活定时器时间到达(tcp_keepalive_time设置,默认2h,期间任何一方没有数据交换,有交换时定时器重置)时,会向客户端发送一定次数(tcp_keepalive_probes设置,默认9次)的保活探测包,每次发送探测包的间隔通过tcp_keepalive_intvl设置,默认75s。
而对每一个保活探测包,客户端可能有三种响应:

  • 双方连接仍然建立,对方接收正常,响应正常ACK,服务器端收到正常ACK后重置保活定时器;
  • 对方已崩溃并重新启动,以RST响应,socket的待处理错误被设置为ECONNRESET,套接口被关闭;
  • 对方无任何相应,则过75s后再发送保活探测包,发送了8次后还是没响应则放弃,套接口待处理错误被设置为ETIMEOUT,套接口被关闭。而如果此过程中获取到”主机不可达”的ICMP包,说明客户端并不是崩溃了,但是不可达,待处理错误被设置为EHOSTUNREACH。

该选项,主要是用来在长时间没有数据连接时探测客户端是否已经异常断开了(崩溃),默认情况下,从双方最后一次通信后,客户端崩溃,则服务器要经过”2h+9*75s”即2小时11分15秒才能获知客户端崩溃,然后断开socket连接。而如果2小时内客户端没崩溃,只是暂时没通信,则会重置保活定时器。

SO_LINGER(参考SO_LINGER)

socket linger选项,设置socket的close行为
使用如下数据结构:

1
2
3
4
struct linger {
int l_onoff; /* 0 = off, nozero = on */
int l_linger; /* linger time */
};

有三种情况:

  1. l_onoff为0,linger选项关闭,l_linger无效,为内核缺省情况,close调用会立即返回给调用者,会将未发送数据送达对端(优雅关闭)
  2. l_onoff为非0值,l_linger为0,close时将丢弃保存在发送缓冲区中的任何数据并发送给对端一个RST,而不是通常的4次挥手,避免了TIME_WAIT状态(强制关闭)
  3. l_onoff为非0值,l_linger为非0值。close时内核将拖延一段时间(l_linger决定),如果发送缓冲区有残留数据,进程将处于休眠状态,直到
    (a). 所有数据发送完,且被对方确认,之后进行正常的终止序列(4次挥手)
    (b). 延迟时间到
    这种情况下,应用程序需要检查close的返回值,如果在发送缓冲区数据发送并确认前延迟时间到,close将返回EWOULDBLOCK错误,且发送缓冲区中的任何数据将丢失,close的成功返回仅告诉我们发送的数据(和FIN)已由对方TCP确认,并不能告诉我们对方应用进程是否已经读取了数据。

l_linger的单位依赖于具体实现