【解锁C语言recv函数阻塞之谜】揭秘非阻塞与阻塞模式下的网络编程技巧

发布时间:2025-05-23 11:14:28

引言

在收集编程中,recv 函数是用于从套接字接收数据的常用函数。但是,对其梗阻与非梗阻形式,很多开辟者感到困惑。本文将深刻探究 recv 函数的梗阻与非梗阻形式,并介绍响应的收集编程技能。

梗阻形式

在梗阻形式下,recv 函数会一直等待,直到有数据可读或产生错误。以下是一些关键点:

  • 前去值
    • > 0:成功接收的字节数。
    • 0:对方曾经封闭连接。
    • < 0:产生错误,须要检查 errno 以断定错误范例。
  • 错误处理
    • EAGAINEWOULDBLOCK:表示不数据可读,但操纵可能持续。
    • ENOTCONN:套接字未连接。
    • ECONNRESET:连接被对方重置。

非梗阻形式

在非梗阻形式下,recv 函数会破即前去,无论能否有数据可读。以下是一些关键点:

  • 前去值
    • > 0:成功接收的字节数。
    • 0:对方曾经封闭连接。
    • < 0:产生错误,须要检查 errno 以断定错误范例。
  • 错误处理
    • EAGAINEWOULDBLOCK:表示不数据可读,但操纵可能持续。
    • ENOTCONN:套接字未连接。
    • ECONNRESET:连接被对方重置。

收集编程技能

  • 利用 selectpoll:这些函数可能检测多个套接字的状况,从而在非梗阻形式下实现多路复用。
  • 设置超时:经由过程 setsockopt 函数,可能设置 recv 函数的超不时光,避免无穷期地等待数据。
  • 处理错误:在处理 recv 函数前去的错误时,要考虑各种可能的错误情况,并采取响应的办法。

示例代码

以下是一个利用 select 函数实现非梗阻 recv 的示例代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <netinet/in.h>

int main() {
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    // ... (设置套接字选项跟连接)

    fd_set read_fds;
    int max_fd = sockfd;

    while (1) {
        FD_ZERO(&read_fds);
        FD_SET(sockfd, &read_fds);

        int sel = select(max_fd + 1, &read_fds, NULL, NULL, NULL);
        if (sel > 0) {
            if (FD_ISSET(sockfd, &read_fds)) {
                char buffer[1024];
                int bytes_received = recv(sockfd, buffer, sizeof(buffer), 0);
                if (bytes_received > 0) {
                    // 处理接收到的数据
                } else if (bytes_received == 0) {
                    // 对方封闭连接
                    break;
                } else {
                    // 产生错误
                    perror("recv");
                    break;
                }
            }
        } else if (sel == 0) {
            // 超时
        } else {
            // 产生错误
            perror("select");
            break;
        }
    }

    close(sockfd);
    return 0;
}

总结

经由过程本文的介绍,信赖你曾经对 recv 函数的梗阻与非梗阻形式有了更深刻的懂得。在现实的收集编程中,公道地利用这些技能可能进步顺序的效力跟坚固性。