MST

星途 面试题库

面试题:C语言中如何实现基本的非阻塞I/O网络编程

在C语言网络编程环境下,简述使用`fcntl`函数将套接字设置为非阻塞模式的步骤,并给出一个简单的示例代码框架,用于在非阻塞套接字上进行数据接收操作。
15.9万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试
  1. 使用fcntl函数将套接字设置为非阻塞模式的步骤
    • 获取当前套接字的文件状态标志: 使用fcntl函数的F_GETFL命令获取套接字当前的文件状态标志。例如,如果套接字描述符为sockfd,可以这样获取:
      int flags = fcntl(sockfd, F_GETFL, 0);
      
    • 设置非阻塞标志: 将获取到的文件状态标志与O_NONBLOCK按位或(|)操作,以设置非阻塞模式。
      flags |= O_NONBLOCK;
      
    • 将新的文件状态标志设置回套接字: 使用fcntl函数的F_SETFL命令将更新后的文件状态标志设置回套接字。
      fcntl(sockfd, F_SETFL, flags);
      
  2. 示例代码框架(用于在非阻塞套接字上进行数据接收操作)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <string.h>

#define BUFFER_SIZE 1024

int main() {
    int sockfd;
    struct sockaddr_in servaddr;

    // 创建套接字
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) {
        perror("Socket creation failed");
        exit(EXIT_FAILURE);
    }

    memset(&servaddr, 0, sizeof(servaddr));
    memset(servaddr.sin_zero, '\0', sizeof(servaddr.sin_zero));

    // 填充服务器地址结构
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(8080);
    servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");

    // 连接到服务器
    if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) != 0) {
        perror("Connect failed");
        close(sockfd);
        exit(EXIT_FAILURE);
    }

    // 将套接字设置为非阻塞模式
    int flags = fcntl(sockfd, F_GETFL, 0);
    flags |= O_NONBLOCK;
    fcntl(sockfd, F_SETFL, flags);

    char buffer[BUFFER_SIZE];
    ssize_t bytesRead;
    while (1) {
        // 在非阻塞套接字上接收数据
        bytesRead = recv(sockfd, buffer, sizeof(buffer), 0);
        if (bytesRead > 0) {
            buffer[bytesRead] = '\0';
            printf("Received: %s\n", buffer);
        } else if (bytesRead == 0) {
            // 对端关闭连接
            printf("Connection closed by peer\n");
            break;
        } else if (errno != EAGAIN && errno != EWOULDBLOCK) {
            perror("Receive error");
            break;
        }
        // 可以在这里进行其他操作,而不是一直等待数据
        sleep(1);
    }

    close(sockfd);
    return 0;
}