对于mysql来说返回的错误代码为99:
perror 99
cannot assign requested address (在出现这样的问题的时候,可以先ulimit -a 看看哪些参数设置的过于严格)
这个是程序端容易出现的问题,由于每次连接都在很短的时间内结束,导致很多的time_wait,以至于用光了可用的端口号,所以新的连接没办法绑定端口。
内核参数net.ipv4.ip_local_port_range 控制可用的端口数量:
sysctl -a | grep port
net.ipv4.ip_local_port_range = 32768 61000
netstat -nt | awk '/^tcp/ {++state[$nf]} end {for(key in state) print key,\t,state[key]}' 检测代码如上:
我们可以试着分析下tcp端开连接的四次握手:
1. 发起方更改状态为fin_wait_1,关闭应用程序进程,发出一个tcp的fin段;
2. 接收方收到fin段,返回一个带确认序号的ack,同时向自己对应的进程发送一个文件结束符eof,同时更改状态为close_wait,发起方接到ack后状态更改为fin_wait_2;
3. 接收方关闭应用程序进程,更改状态为last_ack,并向对方发出一个tcp的fin段;
4. 发起方接到fin后状态更改为time_wait,并发出这个fin的ack确认.ack发送成功后(2msl内)双方tcp状态变为closed.
time_wait状态还需要等2msl后才能返回到closed状态的原因?
这是因为虽然双方都同意关闭连接了,而且握手的4个报文也都协调和发送完毕,按理可以直接回到closed状态(就好比从syn_send状态到establish状态那样);但是因为我们必须要假想网络是不可靠的,你无法保证你最后发送的ack报文会一定被对方收到,因此对方处于last_ack状态下的socket可能会因为超时未收到ack报文,而重发fin报文,所以这个time_wait状态的作用就是用来重发可能丢失的ack报文。
大量的处于time_wait状态的socket, 甚至比处于established状态下的socket多的多,严重影响服务器的处理能力,甚至耗尽可用的socket,停止服务.处理办法有以下两种方式:
1、增加端口号数量
2、减少time_wait连接状态
linux下:
通过调整内核参数解决,vim /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 = 3 #修改系統默认的 timeout 时间
net.ipv4.tcp_max_tw_buckets = 10000#通过设置它,系统会将多余的time_wait删除掉,此时系统日志里可能会显示:『tcp: time wait bucket table overflow』,多数情况下不用在意这些信息。
/sbin/sysctl -p 让参数生效。
本文出自 “技术成就梦想” 博客,,请务必保留此出处