memcached主要使用了以下5个socket选项:
error = setsockopt(sfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&flags, sizeof(flags));
error = setsockopt(sfd, SOL_SOCKET, SO_LINGER, (void *)&ling, sizeof(ling));
error = setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, (void *)&flags, sizeof(flags));
setsockopt(sfd, SOL_SOCKET, SO_SNDBUF, (void *)&avg, intsize)
setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void *)&flags, sizeof(flags));
1. SO_KEEPALIVE: TCP专用,超过一定时间没有数据传输的socket,系统会探测socket两端的主机是否还活着,这个时间值系统通过tcp_keepalive_time定义,默认7200s。意义不是很大,server应该自己检测,自动断开长时间没有数据传输的连接
检测对方主机是否崩溃,避免(服务器)永远阻塞于TCP连接的输入。 设置该选项后,如果2小时内在此套接口的任一方向都没有数据交换,TCP就自动给对方 发一个保持存活探测分节(keepalive probe)。这是一个对方必须响应的TCP分节.它会导致以下三种情况: 对方接收一切正常:以期望的ACK响应。2小时后,TCP将发出另一个探测分节。 对方已崩溃且已重新启动:以RST响应。套接口的待处理错误被置为ECONNRESET,套接 口本身则被关闭。 对方无任何响应:源自berkeley的TCP发送另外8个探测分节,相隔75秒一个,试图得到 一个响应。在发出第一个探测分节11分钟15秒后若仍无响应就放弃。套接口的待处理错 误被置为ETIMEOUT,套接口本身则被关闭。如ICMP错误是“host unreachable(主机不 可达)”,说明对方主机并没有崩溃,但是不可达,这种情况下待处理错误被置为 EHOSTUNREACH。
2. SO_LINGER:TCP专用,设置为{0,0} 表示关闭连接时如果还有数据没发送完,那么等到发送完才真正关闭连接。
3. TCP_NODELAY:TCP专用,关闭Nagle算法。Nagle算法大约是说,如果发送的包太小,系统就等等,等超过一定时间(比如200ms),或者需要发送的包总长度到了一定值才发送,避免频繁发小包。我们写服务器发包的时候,可以控制下每次都是发送一个完整的回包,而这个时候,无论包多大,都没必要等待了,应立即发送。这也是server实时性的要求。
4. SO_SNDBUF:(memcached只有udp协议才设置) UDP协议的时候,设置了这个选项,把发送缓冲区设置为系统允许的最大值。
Sets or gets the maximum socket send buffer in bytes. The kernel doubles this value (to allow space for bookkeeping overhead) when it is set using setsockopt(2), and this doubled value is returned by getsockopt(2). The default value is set by the /proc/sys/net/core/wmem_default file and the maximum allowed value is set by the /proc/sys/net/core/wmem_max file. The minimum (doubled) value for this option is 2048.
5. SO_REUSEADDR:(tcp、udp都设置)绑定的时候,只要绑定的地址没有活动的监听socket绑定,就可以绑定成功。如果不设置这个选项,在重启server的时候,可能因为重启前server的监听socket处于timewait状态,导致无法绑定,一般的server都会设置这个选项
Indicates that the rules used in validating addresses supplied in a bind(2) call should allow reuse of local addresses. For AF_INET sockets this means that a socket may bind, except when there is an active listening socket bound to the address. When the listening socket is bound to INADDR_ANY with a specific port then it is not possible to bind to this port for any local address. Argument is an integer boolean flag.
SO_REUSEADDR可以用在以下四种情况下。(摘自《Unix网络编程》卷一,即UNPv1)
1、当有一个有相同本地地址和端口的socket1处于TIME_WAIT状态时,而你启动的程序的socket2要占用该地址和端口,你的程序就要用到该选项。
2、SO_REUSEADDR允许同一port上启动同一服务器的多个实例(多个进程)。但每个实例绑定的IP地址是不能相同的。在有多块网卡或用IP Alias技术的机器可以测试这种情况。
3、SO_REUSEADDR允许单个进程绑定相同的端口到多个socket上,但每个socket绑定的ip地址不同。这和2很相似,区别请看UNPv1。
4、SO_REUSEADDR允许完全相同的地址和端口的重复绑定。但这只用于UDP的多播,不用于TCP。