2022-05-02-Linux C 中listen函数用法及注意事项
作者:互联网
Linux C 中listen函数用法详细介绍及注意事项:
#include <sys/types.h>
#include <sys/socket.h>
函数原型:int listen(int sockfd, int backlog);
服务端程序 监听来自客户端的tcp socket的连接请求 调用listen导致服务端创建的服务端套接字socket从CLOSED状态转换到LISTEN状态。
sockfd:一个已绑定未被连接的套接字描述符;
backlog:第二个参数是等待连接队列的最大长度,比方说,你将backlog定为10, 当有15个连接请求的时候,前面10个连接请求就被放置在请求队列中,后面5个请求被拒绝。
千万要注意:这个10并不是表示客户端最大的连接数为10, 实际上可以有很多很多的客户端来连接(实践证明也是如此)。
参数backlog定义内核监听队列的最大长度。 在进程正在处理一个连接请求的时候,可能还存在其它的连接请求。因为TCP连接是一个过程,所以可能存在一种半连接的状态,
有时由于同时尝试连接的用户过多,使得服务器进程无法快速地完成连接请求。如果这个情况出现了,服务器进程希望内核如何处理呢?内核会在自己的进程空间里维护一个队
列以跟踪这些完成的连接但服务器进程还没有接手处理的连接(还没有调用accept函数的连接),这样的一个队列内核不可能让其任意大,所以必须有一个大小的上限。这个
backlog告诉内核使用这个数值作为上限。
backlog:APUE中指出,backlog只是一个提示,具体的数值实际上由系统决定。在内核版本2.2之前的Linux中,backlog参数是指所有处于半连接状态(SYN_RCVD)和完全连接
状态(ESTABLISHED)的socket的和的上限。但自内核版本2.2之后,它只表示处于完全连接状态的socket的上限,处于半连接状态的socket的上限则
由/proc/sys/net/ipv4/tcp_max_syn_backlog内核参数定义。backlog参数的典型值是5(4.2BSD支持的最大值)。
当socket函数创建一个套接字时,它被假设为一个主动套接字,也就是说,它是一个将调用connect发起连接的客户端套接字。listen函数把一个未连接的套接字(服务端套
接字)转换成一个被动套接字,指示内核应接受指向该套接字的连接请求。根据TCP状态转换图,调用listen导致服务端套接字sockfd从CLOSED状态转换成LISTEN状态。
listen函数把进程变为一个服务器,并指定相应的套接字sockfd(服务端socket)变为被动连接。
成功: 0;失败:-1;并设置errno。
EADDRINUSE:另一个socket也在监听同一个端口。
EBADF:参数sockfd为非法的文件描述符。
ENOTSOCK:参数sockfd不是文件描述符。
EOPNOTSUPP:套接字类型不支持listen操作。
内核为任何一个给定的监听套接字维护两个队列:
(1)未完成连接队列。每个这样的SYN分节对应其中一项:已由某个客户端程序发出并到达服务器,而服务器正在等待完成相应的TCP三次握手过程。这些套接字处于SYN_ RCVD状态。
(2)已完成连接队列。每个已完成TCP三次握手过程的客户端程序对应其中一项,这些套接字处于ESTABLISHED状态。
客户端与服务器-socket通信流程交互图:
TCP三次握手:
涉及到的维护的两个队列:
查看系统默认backlog:
cat /proc/sys/net/ipv4/tcp_max_syn_backlog
改变系统限制的backlog 大小:
vim /etc/sysctl.conf
最后添加:
net.core.somaxconn = 1024 net.ipv4.tcp_max_syn_backlog = 1024
保存,然后执行:
sysctl -p
1)为什么全连接队列设置大小为16, 而最终ESTABLISHED的个数为17, 多个数值尝试都为+1的关系?
切换到全连接队列的处理逻辑是这样子的: 先判断全连接队列是否已满, 再执行++操作; 如果backlog为16, 第16个ACK(第三次握手)到来时, 全连接队列实际大小为15, 未满, 则++, 此
时才为16; 第17个ACK到来时, 实际大小为16, 而判断逻辑是>, 未满, 又++, 此时为17, 后续的就满了, 符合+1的逻辑关系.
半连接队列-1,全连接队列+1:
标签:02,socket,05,队列,内核,2022,接字,连接,backlog 来源: https://www.cnblogs.com/YiMingXiaoBuYiMengXiaoNai/p/Linux-C-listen-function.html