网络编程:服务器监听+非阻塞设置

cpp 复制代码
// 3. 开始监听
    if (listen(listen_sockfd, 10) < 0) {
        perror("listen failed");
        return 1;
    }
    set_non_blocking(listen_sockfd); // 将监听套接字也设为非阻塞

逐行超详细解释:监听 + 非阻塞设置

这段代码是**TCP服务器从"准备就绪"变成"正式营业"**的关键一步。

先看整体作用(大白话)

c 复制代码
// 告诉操作系统:我这个服务器准备好接收客户端连接了!
// 并且最多让10个客户端排队等待连接
listen(listen_sockfd, 10);

// 把监听的"电话"设置成非阻塞模式
// 意思是:没人打电话时,我可以去干别的事,不用死等
set_non_blocking(listen_sockfd);

逐行深度拆解

第一行:if (listen(listen_sockfd, 10) < 0) {

1. listen() 函数作用

将套接字从「主动套接字」变为「被动监听套接字」

  • 调用前:这个socket只是一个普通文件
  • 调用后:内核开始监听端口,有客户端来连接就会通知程序

2. 第一个参数:listen_sockfd

  • 就是你之前创建、设置复用、绑定好端口的监听套接字
  • 告诉内核:我要监听这个端口上的连接

3. 第二个参数:10监听队列长度 / 等待连接数

这是高频面试题 + 核心知识点

  • 含义:内核中允许排队等待被 accept 的最大客户端连接数
  • 简单理解:"候客区"容量
    • 候客区满了 → 新客户端会连接失败/被拒绝
  • 通常写:5 ~ 128(不要太大也不要太小)

注意:实际内核队列大小会比你填的略大(系统会自动调整),但我们填10就代表最多让10个连接排队。

4. < 0 与错误判断

  • listen() 成功 → 返回 0
  • listen() 失败 → 返回 -1
  • 失败原因:
    • 没调用 bind() 就直接监听
    • 文件描述符非法
    • 端口未绑定

第二行、第三行:perror("listen failed"); return 1;

1. perror("listen failed");

  • 打印系统级错误原因

  • 例子:如果没bind就listen,会打印:

    复制代码
    listen failed: Invalid argument
  • 作用:快速定位bug

2. return 1;

  • 程序异常退出,返回错误码1
  • 服务器监听失败,无法继续运行,直接退出

重点:第四行 set_non_blocking(listen_sockfd);

这行是高性能服务器(非阻塞/IO多路复用)的关键!

1. 什么是阻塞 vs 非阻塞?

【阻塞模式(默认)】
复制代码
没人来连接 → 程序卡住不动,死等
  • 缺点:只能等连接,啥也干不了,无法处理高并发
【非阻塞模式】
复制代码
没人来连接 → 函数立刻返回,不卡住,程序可以去做别的事
  • 优点:配合 select/poll/epoll 实现高并发服务器

2. 这行做了什么?

监听套接字设置为非阻塞模式

  • 以后调用 accept()
    • 有连接 → 正常接收
    • 没连接 → 不卡住,直接返回错误(EAGAIN/EWOULDBLOCK)

3. 为什么要把监听套接字也设为非阻塞?

因为你后面要使用:

  • IO多路复用(select/poll/epoll)
  • 高并发处理
  • 不能让服务器在任何地方被卡住

完整原理流程图(一看就懂)

复制代码
客户端发送连接请求 → 到达服务器端口
↓
内核自动接收连接(TCP三次握手内核完成!)
↓
连接放入「等待队列」(最多放10个)
↓
服务器调用 accept() → 从队列取走连接

listen() 的作用:开启这个内核队列,开始自动接收连接!


极简总结(超好记)

  1. listen():开启监听,让内核帮你自动处理TCP连接
  2. 参数10:内核等待队列长度(候客区最多10人)
  3. 返回值判断:监听失败就报错退出
  4. set_non_blocking :设置非阻塞模式,不卡住程序,支持高并发
  5. 核心意义 :服务器正式开始对外接收客户端连接

一句话总结

listen 让内核帮你排队等连接,非阻塞让你的程序永远不会卡死,这是高性能服务器的标准写法!

相关推荐
新时代牛马1 小时前
嵌入式网络完整篇:从LwIP/以太网驱动到 Linux netdev 与排障
linux·网络·php
前端世界2 小时前
Linux服务器实战:NTP时间同步、SELinux权限与rsyslog日志管理,一次搞懂三大运维问题
linux·运维·服务器
Android系统攻城狮2 小时前
Linux Gstreamer深度解析之gst_audio_converter_new调用流程与实战(二十)
linux·运维·服务器·gstreamer音视频·音视频进阶
上海云盾-小余2 小时前
BGP 高防底层原理:TCP 异常流量识别与清洗机制
运维·网络·tcp/ip
captain3762 小时前
▲网络原理(2)-TCP
java·服务器·网络·tcp/ip·java-ee
同元软控3 小时前
从排队、碰撞到信号波形:基于Sysevents的网络—信号一体化仿真
网络
言乐63 小时前
Python加速器4跨境网络加速器
运维·服务器·开发语言·网络·python
疯狂打码的少年5 小时前
【计算机网络】IPv6基础(特点、表示法、与IPv4对比)
网络·笔记·计算机网络
门思科技5 小时前
LoRaWAN 网络容量估算:一个 SX1302 网关到底能带多少设备
开发语言·网络·php
今天AI了吗9 小时前
什么是 AI Agent?它与直接调用大模型 API 有何区别
java·网络·人工智能·架构·java-ee