我在学习listen函数的过程中,一开始对于backlog参数有股很模糊的理解,并不知道这个东西是干什么的,有什么用处?
在后面的学习中,查询了一些资料,在这里对于我自己理解的backlog参数做一个简单的整理,方便自己以后查阅.
-
listen函数的回顾
backlog参数和TCP/IP协议有密切相关的联系
要了解backlog参数的作用,需要回到listen函数中来进行理解的. -
首先我们来谈谈listen函数有什么作用?
listen函数仅仅由TCP服务器来进行调用,它在网络编程中用来使服务器端来开始 监听端口的系统调用,即把主动连接的套接字变化为被连接的套接字,检测套接字上有无I/O事件. -
listen函数的定义
#include<sys/socket.h>
int listen(int sockfd,int backlog); -
listen函数一般在socket和bind函数之后,accept函数之前调用
-
backlog参数的含义
我查询了网上很多资料,他们的说法都各不一样
都是内核为一个给定的监听套接字维护队列,我自己的理解是内核为给定的监听套接字维护两个队列- 一个是SYN队列,某个客户发出并到达服务器,而服务器正在等待TCP的三次握手,处于SYN_RCVD状态
- 一个是ACCEPT队列,保存着已经完成了TCP的三次握手
而backlog的值为已经完成了TCP三次握手的队列值,也就是已完成队列的值
-
backlog参数的理解
由于TCP使用的是三次握手,在连接到达ESTABLISHED状态值之前必定会经过其中间状态SYN_RCVD,并且可以由accpet函数返回到应用程序.
历史上,BSD派生系统实现的TCP通常使用内核为LISTEN状态的socket维护一个队列,其中存放着SYN_RECEIVED和ESTABLISHED状态的套接字,backlog会是这个队列的大小,该选择意味如果达到最大的backlog的时候,系统将不会响应与SYN分组发送回SYN/ACK分组。通常,TCP的实现会简单丢弃掉SYN分组,客户端会重新启动 -
但是通过查询man手册可以得到,在内核2.2之后,socket backlog参数被形为的改变了,它指等待accept的完全建立的套接字的队列长度,而不是不完全连接请求的数量。不完全连接的长度可以使用/proc/sys/net/ipv4/tcp_max_syn_backlog设置。
意味着内核会设置两个队列 -
Berkeley的实现给backlog设置了一个模糊因子,把它乘1.5得到未处理队列的最大长度,一般设置为backlog实际允许最多有8项在排队
-
当客户端的第一个SYN到达的时候,TCP会在未完成队列中增加一个新的记录然后回复给客户端三路握手中的第二个分节(服务端的SYN和针对客户端的ACK),这条记录会在未完成队列中一直存在,直到三路握手中的最后一个分节到达,或者直到超时(Berkeley时间将这个超时定义为75秒)。
-
如果当客户端SYN到达的时候队列已满,TCP将会忽略后续到达的SYN,但是不会给客户端发送RST信息,因为此时允许客户端重传SYN分节,如果返回错误信息,那么客户端将无法分清到底是服务端对应端口上没有相应应用程序还是服务端对应端口上队列已满这两种情况。