xd96dx Docs
  • c/c++
    • 网络编程
      • linux 网络
        • linux 网络io模型
        • Signal-Driven I/O Model(信号驱动)
        • Asynchronous I/O Model(异步IO)
      • IO多路复用
        • select 示例
        • poll 示例
        • epoll 示例
      • Reactor实例之 muduo 源码分析
    • stl实现
      • 容器(Containers)
        • Vector(动态数组)
        • List(双向链表)
        • Deque(二级动态数组)
  • 游戏开发
    • skynet 从demo到源码
      • server-client demo
      • skynet 源码分析-启动流程之初始化
      • skynet 源码分析-启动流程之创建service
      • skynet 源码分析-启动流程之线程池启动
Powered by GitBook
On this page
  • code
  • 优缺:
  • 优点: 跨平台
  • 缺点:...
  1. c/c++
  2. 网络编程
  3. IO多路复用

select 示例

code

#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <string.h>

constexpr int PORT = 8080;
constexpr int BUFFER_SIZE = 1024;

void setup(int &sockfd) {
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) {
        perror("Failed to create socket");
        exit(EXIT_FAILURE);
    }

    sockaddr_in serverAddr{};
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_addr.s_addr = INADDR_ANY;
    serverAddr.sin_port = htons(PORT);

    if (bind(sockfd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0) {
        perror("Failed to bind socket");
        close(sockfd);
        exit(EXIT_FAILURE);
    }

    if (listen(sockfd, 5) < 0) {
        perror("Failed to listen on socket");
        close(sockfd);
        exit(EXIT_FAILURE);
    }

    // Set non-blocking mode
    fcntl(sockfd, F_SETFL, O_NONBLOCK);
    std::cout << "Server listening on port " << PORT << std::endl;
}

int main() {
    int serverSock, maxfd;
    setup(serverSock);

    fd_set readfds;
    FD_ZERO(&readfds);

    while (true) {
        // Add server socket and standard input to the set
        FD_SET(serverSock, &readfds);
        FD_SET(STDIN_FILENO, &readfds);
        maxfd = std::max(serverSock, STDIN_FILENO);

        // Set timeout for select (2 seconds)
        timeval timeout{};
        timeout.tv_sec = 2;
        timeout.tv_usec = 0;

        int activity = select(maxfd + 1, &readfds, nullptr, nullptr, &timeout);
        if (activity < 0 && errno != EINTR) {
            perror("select error");
        } else if (activity == 0) {
            std::cout << "Timeout occurred! No activity detected.\n";
            continue;
        }

        // Check if there's activity on the server socket
        if (FD_ISSET(serverSock, &readfds)) {
            sockaddr_in clientAddr{};
            socklen_t addrLen = sizeof(clientAddr);
            int clientSock = accept(serverSock, (struct sockaddr *)&clientAddr, &addrLen);
            if (clientSock >= 0) {
                std::cout << "New connection from " << inet_ntoa(clientAddr.sin_addr) << std::endl;
                close(clientSock);
            }
        }

        // Check if there's input on stdin
        if (FD_ISSET(STDIN_FILENO, &readfds)) {
            char buffer[BUFFER_SIZE];
            ssize_t bytesRead = read(STDIN_FILENO, buffer, sizeof(buffer) - 1);
            if (bytesRead > 0) {
                buffer[bytesRead] = '\0';
                std::cout << "Received input: " << buffer << std::endl;
            }
        }
    }

    close(serverSock);
    return 0;
}

优缺:

优点: 跨平台

缺点:...

  1. 监听文件描述符多了之后,慢的一匹,每次都要遍历所有fd

  2. 文件描述符上限1024

  3. 每次调用select,都需要把文件描述符集合从用户态拷贝到内核态

PreviousIO多路复用Nextpoll 示例

Last updated 6 months ago