一、 为什么需要 Listen?
默认情况下,socket()创建的套接字是主动的(准备去连接别人)。
而服务器需要的是被动套接字(等着被别人连接)。
listen()函数的作用就是把套接字从“主动模式”切换到“被动监听模式”。打个比方,bind是租好了店面,listen就是打开店门,挂上“营业中”的牌子。
二、 核心参数:神秘的backlog
intlisten(intsockfd,intbacklog);sockfd: 已经绑定好的监听套接字。backlog:未完成连接队列的最大长度。
1.backlog到底是什么?
很多新手误以为它是“服务器能支持的最大在线人数”。错!
backlog指的是同一时刻正在排队等待被accept接入的连接数。
- 想象一下奶茶店:
- 店里能容纳 100 人喝奶茶(系统总资源)。
- 柜台前只能排队 5 个人(
backlog)。 - 如果收银员(
accept)动作很快,即便有一万个顾客陆续来,只要排队不超过 5 个,系统就能正常运转。 - 如果收银员不动了,第 6 个人就排不进来了。
2. 这个值设多大合适?
- 笔记重点:内核中通常有一个硬限制(如 128)。即便你把
backlog设为 10000,系统也可能只认 128。 - 行为:
- 如果设置 5,系统会同时维护 5 个等待连接。
- 如果有更多连接涌入,系统会分批轮询处理。
- 如果队列满了,多余的客户端连接请求可能会收到“Connection Refused”错误,或者被暂时忽略(依赖 TCP 重传机制)。
三、 代码实战:验证 Backlog 的排队效应
为了验证backlog的作用,我们设计一个**“偷懒”服务器**:它开启监听,但死活不调用accept取出连接。这样,连接队列很快就会被填满。
1. 偷懒的服务器 (lazy_server.c)
#include<stdio.h>#include<unistd.h>#include<arpa/inet.h>#include<stdlib.h>intmain(){int