MST
星途 面试题库

面试题:C++ 同步多路复用之select实现基础

请用C++ 结合select函数实现一个简单的同步多路复用程序,监听两个socket描述符,当其中任意一个有可读事件时,输出对应的信息。假设已经有两个有效的socket描述符sock1和sock2。
27.6万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试
#include <iostream>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <cstring>
#include <sys/select.h>

#define BUFFER_SIZE 1024

int main() {
    int sock1 = socket(AF_INET, SOCK_STREAM, 0);
    int sock2 = socket(AF_INET, SOCK_STREAM, 0);

    // 假设sock1和sock2已经被正确初始化和连接

    fd_set read_fds;
    FD_ZERO(&read_fds);
    FD_SET(sock1, &read_fds);
    FD_SET(sock2, &read_fds);

    char buffer[BUFFER_SIZE];
    while (true) {
        fd_set tmp_fds = read_fds;
        int activity = select(std::max(sock1, sock2) + 1, &tmp_fds, nullptr, nullptr, nullptr);
        if (activity < 0) {
            std::cerr << "select error" << std::endl;
            break;
        } else if (activity > 0) {
            if (FD_ISSET(sock1, &tmp_fds)) {
                int bytesRead = recv(sock1, buffer, sizeof(buffer), 0);
                if (bytesRead > 0) {
                    buffer[bytesRead] = '\0';
                    std::cout << "Data from sock1: " << buffer << std::endl;
                }
            }
            if (FD_ISSET(sock2, &tmp_fds)) {
                int bytesRead = recv(sock2, buffer, sizeof(buffer), 0);
                if (bytesRead > 0) {
                    buffer[bytesRead] = '\0';
                    std::cout << "Data from sock2: " << buffer << std::endl;
                }
            }
        }
    }

    close(sock1);
    close(sock2);
    return 0;
}

上述代码中:

  1. 首先创建了两个套接字sock1sock2,假设它们已经正确初始化和连接。
  2. 使用fd_set来管理要监听的文件描述符集合,并使用FD_ZEROFD_SET初始化集合。
  3. while循环中,使用select函数监听文件描述符集合中的可读事件。
  4. 根据select的返回值,判断哪个套接字有可读事件,并通过recv函数接收数据并输出。
  5. 最后关闭两个套接字。

注意,在实际应用中,需要处理更多的错误情况,如套接字创建、绑定、连接错误等,以及可能的内存管理和资源释放问题。同时,上述代码基于类Unix系统,在Windows系统上需要使用WSASelect等Windows特定的函数。