网络编程问题总结(一)
关于listen的backup参数
listen的第二个参数,在网上有各种版本的解释,有人说是三次握手成功等待被accept的请求队列长度,有人说是尚未成功建立连接的队列长度,有人说是二者队列长度之和。
#man listen
# man tcp
从man手册可以发现:从linux 2.2开始,backlog是指已经建立连接等待被accept的队列长度,而未成功建立连接的队列长度由tcp_max_syn_backlog决定,这个长度默认为256,在系统内存大于128M时,会设置为1024;在内存小于32M时,被设置为128。
关于打开文件数限制
系统打开文件数的限制可通过ulimit –n查看,默认为1024(2.6.18-92.el5),对于服务器来说,这个数目是远远不够的,通过ulimit –n max-open-file进行修改。
通过ulimit的设置会在下次重启后失效,下次启动会继续使用默认值,故对于服务器来说,通常应该在开始服务前通过setrlimit来修改打开文件数的限制,man setrlimit。
关于TIME_WAIT
TCP主动close一方,在回复最后的ACK后,会有2MSL的TIME_WAIT时间,在没有设置地址重用的情况下,使用的地址(ip:port)是不能被使用的。
存在TIME_WAIT状态的理由:
(1)可靠地实现TCP全双工连接的终止,即在ack丢失时,可以重发ack。
(2)允许老的重复分节在网络中消逝,如果在同一个地址上的连接马上被重新建立,则在老连接上仍存在的数据会对新连接产生影响。
TIME_WAIT可能存在的副作用:
(1) 在服务器端某地址上启动服务程序,如果未设置地址重用,则关闭服务后,不能马上重启服务,会提示地址也被使用(bind: Address already in use)。
(2) 在客户端,如果同时建立很多到服务器的短连接(长连接该问题也会存在,但不能解决),则客户端会存在很多TIME_WAIT状态的连接,如果未设置地址重用,则最终客户端会找不到合适的端口来建立连接(Cannot assign requested address)。
对于问题(2),可通过setsockopt设置端口重用来解决,如果使用的是socket的封装,例如rpc等,则可通过sysctl来更改配置。
# 编辑 /etc/sysctl.conf,加入
net.ipv4.tcp_syncookies = 1 #表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;
net.ipv4.tcp_tw_reuse = 1 #表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
net.ipv4.tcp_tw_recycle = 1 #表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。
net.ipv4.tcp_fin_timeout = 30 #修改系統默认的TIMEOUT时间
# sysctl –p 加载配置
其中开启地址重用、开启快速回收、修改fin_timeout都能从一定程度上解决问题(2)。