09_百万并发的TCP服务器

一. 百万并发的TCP服务器介绍

上一节已经介绍了TCP服务器的两个版本的实现,跳转:08_TCP服务器:一请求一线程 & epoll
但是即使是使用了epoll也无法做到100万的并发量。本节将针对上一节 08_TCP服务器:一请求一线程 & epoll的代码基础上进行优化,最终实现百万并发的TCP服务器。

并发量是什么?

并发量指的是一秒钟处理的客户端的请求数量,即qbs。

我们首先来测试一下上节使用epoll实现的TCP服务器的并发数量, 运行该程序需要指定服务器的端口 (只有1个端口)

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include <netinet/tcp.h>
#include <arpa/inet.h>

#include <unistd.h>
#include <sys/epoll.h>

#define BUFFER_LENGTH 1024
#define EPOLL_SIZE 1024

int main(int argc, char *argv[]) {
    if(argc < 2) {
        printf("Param Error\n");
        return -1;
    }

    int port = atoi(argv[1]);
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(struct sockaddr_in));

    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = INADDR_ANY;
    
    if(bind(sockfd, (struct sockaddr*)&addr, sizeof(struct sockaddr_in)) < 0) {
        perror("bind");
        return -2;
    }

    if(listen(sockfd, 5) < 0) {
        perror("listen");
        return -3;
    }
    int epfd = epoll_create(1);
    struct epoll_event events[EPOLL_SIZE] = {0};

    struct epoll_event ev;
    ev.data.fd = sockfd;
    ev.events = EPOLLIN;
    epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &ev);

    while(1) {
        int nready = epoll_wait(epfd, events, EPOLL_SIZE, 5);
        if(nready == -1) continue;

        for (int i = 0; i < nready; i ++) {
            if(events[i].data.fd == sockfd) {
                struct sockaddr_in client_addr;
                memset(&client_addr, 0, sizeof(struct sockaddr_in));
                socklen_t client_len = sizeof(client_addr);
                int clientfd = accept(sockfd, (struct sockaddr*)&client_addr, &client_len); 

                ev.data.fd = clientfd;
                ev.events = EPOLLIN | EPOLLET;
                epoll_ctl(epfd, EPOLL_CTL_ADD, clientfd, &ev);
            }
            else {
                int clientfd = events[i].data.fd;
                char buffer[BUFFER_LENGTH] = {0};
                int len = recv(clientfd, buffer, BUFFER_LENGTH, 0);
                if(len == 0) {
                    //disconnect
                    close(clientfd);
                    ev.data.fd = clientfd;
                    ev.events = EPOLLIN | EPOLLET;
                    epoll_ctl(epfd, EPOLL_CTL_DEL, clientfd, &ev);
                    break;
                } else if(len < 0) {
                    close(clientfd);
                    ev.data.fd = clientfd;
                    ev.events = EPOLLIN | EPOLLET;
                    epoll_ctl(epfd, EPOLL_CTL_DEL, clientfd, &ev);
                    break;
                } else {
                    printf("Recv: %s %d byte(s)\n", buffer, len);
                }
            }
        }

    }
    return 0;
}
posted @ 2025-11-21 10:08  Xiaomostream  阅读(0)  评论(0)    收藏  举报