关于高并发服务器的listen函数参数设置

int listen(int fd, int backlog);


socket系统调用listen只被tcp 服务器使用,他做两件事:
1. 将未链接的套接口转换为被动套接口,指示内核接受向此套接口的连接请求,调用此系统调用后tcp 状态机有close转换到listen.
2.第二个参数制定了内核为此套接口排队的最大连接个数。
关于第二个参数,对于给定的监听套接口,内核要维护两个队列,未链接队列和已连接队列,根据tcp 三路握手过程中三个分节来分隔这两个队列。
  服务器处于listen状态时收到客户端syn 分节(connect)时在未完成队列中创建一个新的条目,然后用三路握手的第二个分节即服务器的syn 响应及对客户端syn的ack,此条目在第三个分节到达前(客户端对服务器syn的ack)一直保留在未完成连接队列中,如果三路握手完成,该条目将从未完成连接队列搬到已完成连接队列尾部。当进程调用accept时,从已完成队列中的头部取出一个条目给进程,当已完成队列为空时进程将睡眠,直到有条目在已完成连接队列中才唤醒。
 
backlog被规定为两个队列总和的最大值,大多数实现默认值为5,但在高并发web服务器中此值显然不够,lighttpd中此值达到128*8.需要设置此值更大一些的原因是未完成连接队列的长度可能因为客户端SYN的到达及等待三路握手第三个分节的到达延时而增大。
当客户端发起connect而导致发送syn分节给服务器端握手,如果这时两个队列都是满的,tcp就忽略此分节,并且不发RST,这将导致客户端TCP重发SYN(超时),服务器端忽略syn而不发RST响应的原因是如果发RST ,客户端connect将立即返回错误,强制客户端进程处理这种情况,而不是让tcp的正常重传机制来处理。实际上所有源自Berkeley的实现都是忽略新的SYN分节。
还有,backlog为0 时在linux上表明润许不受限制的连接数,这是一个缺陷,因为它可能会导致SYN Flooding(拒绝服务型攻击), 下一篇文章会简单解释。

linux 系统tcp /ip协议栈有个选项可以设置未链接队列大小

tcp_max_syn_backlog


cat /proc/sys/net/ipv4/tcp_max_syn_backlog 
1024

你可能感兴趣的:(关于高并发服务器的listen函数参数设置)