世界足球俱乐部杯

socket阻塞和非阻塞的区别是什么

出处:网络整理 发布于:2025-06-10 17:08:46

Socket 的阻塞(Blocking)和非阻塞(N-blocking)模式是网络编程中两种重要的 I/O 操作方式,主要区别在于程序在等待 I/O 操作完成时的行为。以下是它们的区别:

1. 阻塞模式(Blocking)

特点

  • 调用会一直等待,直到操作完成或出错才返回。

  • 线程/进程会被挂起,无法执行其他任务,直到 I/O 操作结束。

  • 适用于简单、同步的网络通信,编程模型直观。

常见阻塞操作

  • recv():如果没有数据到达,线程会一直阻塞,直到有数据。

  • send():如果发送缓冲区满,线程会阻塞,直到数据被发送。

  • accept():如果没有新连接,线程会阻塞,直到有客户端连接。

  • connect():在 TCP 连接建立成功或失败前,线程会阻塞。

示例(TCP 阻塞 recv)

c

char buffer[1024]; int bytes = recv(sockfd, buffer, sizeof(buffer), 0); // 阻塞,直到收到数据或出错 printf("Received: %d bytes\n", bytes);

  • 如果没有数据可读,程序会卡在 recv() 处,直到数据到达或连接关闭。

优点

  • 编程简单,逻辑清晰。

  • 适合低并发、同步处理的场景。

缺点

  • 并发能力差:每个连接需要一个线程/进程,资源消耗大(C10K 问题)。

  • 响应性差:如果一个连接阻塞,整个线程无法处理其他任务。


2. 非阻塞模式(Non-blocking)

特点

  • 调用立即返回,无论操作是否完成。

  • 线程不会被挂起,可以继续执行其他任务。

  • 需要轮询或事件驱动(如 select/poll/epoll) 来检查 I/O 状态。

  • 适用于高并发、异步 I/O 场景(如 Web 、游戏服务器)。

如何设置非阻塞 Socket?

在 Linux 下:

c

int flags = fcntl(sockfd, F_GETFL, 0); fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); // 设置为非阻塞

在 Windows 下:

c

unsigned long mode = 1; ioctlsocket(sockfd, FIONBIO, &mode); // 设置为非阻塞

常见非阻塞操作

  • recv():如果没有数据,立即返回 -1,并设置 errno = EWOULDBLOCK(Linux)或 WSAEWOULDBLOCK(Windows)。

  • send():如果发送缓冲区满,立即返回 -1,表示无法立即发送。

  • accept():如果没有新连接,立即返回 -1

  • connect():立即返回 -1,并设置 errno = EINPROGR(连接仍在进行)。

示例(非阻塞 recv + 轮询)

c

char buffer[1024]; int bytes = recv(sockfd, buffer, sizeof(buffer), 0); if (bytes == -1) {
    if (errno == EWOULDBLOCK) {
        printf("No data available, try later.\n");
    } else {
        perror("recv error");
    } } else {
    printf("Received: %d bytes\n", bytes); }

  • 如果没有数据,recv() 不会阻塞,而是立即返回错误,程序可以继续执行其他逻辑。

优点

  • 高并发:单线程可以管理多个 Socket(配合 select/epoll)。

  • 响应性好:不会因为某个 Socket 卡住整个程序。

  • 适合高性能服务器(如 Nginx、Redis)。

缺点

  • 编程复杂:需要处理 EWOULDBLOCK 和异步状态。

  • 占用可能较高(如果使用忙轮询)。

3. 对比总结

特性阻塞模式非阻塞模式
调用行为等待操作完成才返回立即返回,成功/失败需检查
线程状态挂起,不占用 CPU继续执行,可处理其他任务
并发能力低(需多线程)高(单线程 + I/O 多路复用)
编程复杂度简单较复杂(需处理异步状态)
适用场景简单客户端、低并发服务器高并发服务器(Web、游戏、实时系统)

4. 如何选择?

  • 阻塞模式:适合简单应用,如客户端程序、低并发的服务端(如 FTP)。

  • 非阻塞模式:适合高并发服务器(如 HTTP Server、WebSocket),通常结合 select/poll/epoll(Linux)或 IOCP(Windows)使用。

5. 扩展:I/O 多路复用(select/poll/epoll)

非阻塞 Socket 通常结合 I/O 多路复用 使用,避免忙轮询:

  • select() / poll():检查多个 Socket 是否可读/可写(跨平台,但性能一般)。

  • epoll()(Linux):高效事件通知机制,支持海量连接。

  • kqueue()(FreeBSD/MacOS):类似 epoll

  • IOCP(Windows):异步 I/O 模型。

示例(epoll + 非阻塞 Socket)

c

int epfd = epoll_create1(0); struct epoll_event ev;
ev.events = EPOLLIN | EPOLLET; // 边缘触发(Edge-Triggered)
ev.data.fd = sockfd; epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &ev);
 while (1) {
    int n = epoll_wait(epfd, events, MAX_EVENTS, -1);
    for (int i = 0; i < n; i++) {
        if (events[i].data.fd == sockfd) {
            // 有数据可读,调用 recv(不会阻塞)
            recv(sockfd, buf, sizeof(buf), 0);
        }
    } }

总结

  • 阻塞 Socket:简单但低效,适合低并发。

  • 非阻塞 Socket:复杂但高效,适合高并发,通常配合 epoll/select 使用。

版权与免责声明

凡本网注明“出处:维库电子市场网”的所有作品,版权均属于维库电子市场网,转载请必须注明维库电子市场网,//domainnameq.cn,违反者本网将追究相关法律责任。

本网转载并注明自其它出处的作品,目的在于传递更多信息,并不代表本网赞同其观点或证实其内容的真实性,不承担此类作品侵权行为的直接责任及连带责任。其他媒体、网站或个人从本网转载时,必须保留本网注明的作品出处,并自负版权等法律责任。

如涉及作品内容、版权等问题,请在作品发表之日起一周内与本网联系,否则视为放弃相关权利。

OEM清单文件: OEM清单文件
*公司名:
*联系人:
*手机号码:
QQ:
有效期:

扫码下载APP,
 一键连接广大的电子世界。

在线人工客服

买家服务:
卖家服务:
技术客服:

0571-85317607

网站技术支持

13606545031

客服在线时间周一至周五
 9:00-17:30

关注官方微信号,
第一时间获取资讯。

建议反馈

联系人:

联系方式:

按住滑块,拖拽到最右边
>>
感谢您向阿库提出的宝贵意见,您的参与是维库提升服务的动力!意见一经采纳,将有感恩红包奉上哦!