⟅UNIX网络编程⟆⦔listen函数

说在前面

基本说明

在这里插入图片描述

图一

listen函数由服务器调用,主要负责监听套接字的连接以及规定套接字连接队列的容量(见下面英文原文)

listen for socket connections and limit the queue of incoming connections

  1. socket函数创建一个套接字时,该套接字被称为主动套接字,即一个将要调用connect函数的客户套接字。而listen函数将一个未连接的套接字转换为被动套接字,指示内核应接受指向该套接字的连接请求
  2. listen函数同时规定指向该套接字的连接请求所形成的队列的容量(规定内核为相应套接字排队的最大连接个数),该容量由backlog参数指定。
  • 定义

    #include <sys/socket.h>
    int listen(int sockfd, int backlog)
    
    参数说明:
    • sockfd
      套接字描述符。
    • backlog
      内核为任意一个给定的监听套接字维护两个队列:
      • 未完成连接队列
        该队列中的连接均处于满足以下条件的状态:客户发送的SYN包已到达服务器,服务器正在等待完成对应的TCP三路握手。即SYN_RCVD状态(该状态为从服务器角度查看的状态,见图一)。
      • 已完成连接队列
        该队列中的连接均已经完成TCP三路握手,并处于ESTABLISHED状态。
        pic
    图二
  • 具体细节

    • 当来自客户的SYN到达时,TCP在未完成队列中创建一个新项(见图二);然后向客户发送服务器的SYN响应,捎带ACK(见图三)。创建的新项会保留在未完成连接队列中,直到三路握手完成(即ACK k+1 到达或者响应超时)。
      在这里插入图片描述
      图三
    • 若三路握手正常完成,上述新项将从未完成连接队列移动到已完成连接队列的队尾(见图二)。
    • 当进程调用accept函数时,已完成连接队列的队首将被返回给进程(见图二);若此时该队列为空,进程将进入睡眠状态,直到TCP往该队列中添加新项。

补充说明

  • listen函数的backlog参数曾被定义为两队列(已完成连接和未完成队列)总和的最大值。
  • 源自Berkeley的实现给backlog增设了一个模糊因子:把它(指backlog)乘以1.5得到未处理队列(并不是未完成连接)最大长度。举个栗子,backlog值为5时通常有最多8项在排队。
  • 不要把backlog设置为0,因为不同系统的实现对于设置为0的情况有不同的解释。若不想让任何客户连接,请关闭套接字。
  • 假设在图三中的三路握手均正常完成(没有丢失分节,没有重传),那么未完成队列中的任何一项在该队列中的存留时间为一个RTT,RTT值取决于特定的客户与服务器。
  • 历史上使用的样例中backlog通常设置为5,在过去已经足够;但是在现在根本不够。
  • backlog应设置为多大?
    一种方式是设置一个足够大的值,固定在源代码中;
    另一种是设置一个默认值,但是允许使用命令行选项或者环境变量覆写
    同时,指定一个比内核可承受的值还大的backlog值也是可以的,内核会将其修改为可接受的最大值,并且不返回错误。
    void Listen(int fd, int backlog)
    {
    	char *ptr;
    
    	// 通过获取环境变量LISTENQ覆写backlog值
    	if( (ptr = getenv("LISTENQ")) != NULL)
    		backlog = atoi(ptr);
    
    	if( listen(fd, backlog) < 0)
    		err_sys("listen error");
    }
    
  • 当一个SYN分节到达时(见图二),若这些队列是满的,TCP会忽略该分节,也就是不发送RST(见connect函数)。原因:该情况是暂时的,客户将重发SYN,期望在不久后这些队列中会有可用空间。若发送RST,那么connect将立即返回错误,那么应用进程就需要处理这种情况,浪费了TCP的重传机制。另外,客户也无法区分该RST是“该端口没有服务器在监听”还是“该端口有服务器在监听,但是队列已满”。
  • 在三路握手完成之后,accept调用之前,客户传输的数据应由服务器TCP排队,最大数据量为相应已连接套接字的接收缓冲区的大小。
  • 不同操作系统下对backlog的解释
    AIX/MacOS为传统Berkeley算法,Solaris接近于该算法,FreeBSD为backlog+1
backlog实际已排队连接的最大数目
MACOS 10.2.6/AIX 5.1Linux 2.4.7HP-UX 11.11FreeBSD 4.8/FreeBSD 5.1Solaris 2.9
013111
124122
245334
356445
477656
588768
61099710
7111010811
8131112913
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值