1.listen队列剖析
int listen(int socketfd ,int backlog);
要理解好backlog这个参数,我们需要谈一谈“监听套接字 队列”的话题;
1.1监听套接字的队列
对于一个调用listen()进行监听的套接字,操作系统会给这个套接字维护两个队列;
a)未完成连接队列
当客户端发送tcp连接三次握手的第一次【syn包】给服务器的时候,服务器就会在未完成队列中创建一个跟这个syn包对应的一项,
其实,我们可以把这项看成是一个半连接【因为连接还没建立起来呢】,这个半连接的状态会从LISTEN变成SYN_RCVD状态,同时给客户端返回第二次握手包【syn,ack】
这个时候,其实服务器是在等待完成第三次握手;
b)已完成连接队列
当第三次握手完成的时候,这个连接就变成了ESTABLISTENED状态,每个已完成三次握手的客户端,都放在这个队列中作为一项;
backlog曾经的含义就是“未完成连接队列”数加“已完成连接队列”数之和不能超过backlog
1.2 accept()函数
accpept()函数 就是从已完成连接队列的队首位置中取出来一项【每一项都是一个已完成三次握手的TCP连接】,返回给进程
如果已完成连接队列是空的呢?那么accept()会一致卡在这里【休眠】等待,一直到已完成队列中有一项时才会被唤醒;
所以,从编程角度,我们要尽快的用accept()把已完成队列中的数据【TCP连接】取走
accpet()返回的是套接字,这个套接字就代表那个已经用三次握手建立起来的TCP连接 ,这个套接字与服务器监听端口的监听套接字不同,需要严格区分