8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

C++ 中的套接字:处理 Windows 操作系统中的多个并发请求

Matthias Auswöger 2月前

27 0

我尝试构建一个多线程服务器,这样当有多个并发请求时,服务器可以同时处理它们。但是,我的代码仍然需要等待第一个请求完成才能执行

我尝试构建一个多线程服务器,这样当有多个并发请求时,服务器可以同时处理它们。但是,我的代码仍然需要等待第一个请求完成后才能开始第二个请求。

下面是我的代码

int main() {
    //server startup
    WSADATA wsaData;
    int server_start = WSAStartup(MAKEWORD(2,2),&wsaData);
    if(server_start) {
        cout<<"Error at startup socket!"<<endl;
        return 0;
    }

    //server init
    SOCKET server_socket = socket(AF_INET, SOCK_STREAM, 0);
    if(!server_socket) {
        printf("socket function failed with error: %u\n", WSAGetLastError());
        return 0;
    }

    sockaddr_in server_address;
    memset(&server_address,0,sizeof(server_address));
    server_address.sin_family = AF_INET;
    server_address.sin_addr.s_addr = INADDR_ANY;
    server_address.sin_port = htons(PORT);

    //server binding
    if(bind(server_socket,(sockaddr*)&server_address,sizeof(server_address))) {
        cout<<"socket function fail at binding"<<endl;
        return 0;
    }

    //server listening
    if(listen(server_socket,5) == -1) {
        cout<<"Fail at listening"<<endl;
        return 0;
    } 
    cout<<"Server listening at port "<<PORT<<endl;

    while(true) {
        //init client data
        sockaddr_in client_address;
        socklen_t client_address_len = sizeof(client_address);

        //server accept
        SOCKET client_socket = accept(server_socket,(sockaddr*)&client_address,&client_address_len);
        cout<<"Client socket init : "<<client_socket<<endl;
        if(!client_socket) {
            cout<<"Error when accepting connection"<<endl;
            continue;
        }
        cout<<"Accepeted connection from "
            <<inet_ntoa(client_address.sin_addr)<<":"<<ntohs(client_address.sin_port)<<endl;
        
        thread(handle_connection, client_socket).detach();
    }

    WSACleanup();
    return 0;
}
int handle_connection(SOCKET client_socket) {
    cout<<"Thread with id "<<this_thread::get_id()<<" with socket "<<client_socket<<endl;

    //handle HTTP request
    char buffer[BUFFER_SIZE];
    memset(buffer,0,BUFFER_SIZE);
    SSIZE_T bytes_recived = recv(client_socket,buffer,BUFFER_SIZE,0);
    if(bytes_recived <= 0) {
        cout<<"Failed to read the request!"<<endl;
        return 0;
    }

    //parse request
    string request(buffer,bytes_recived);
    SSIZE_T first_space = request.find(' ');
    string method = request.substr(0, first_space);
    SSIZE_T second_space = request.find(' ', first_space + 1);
    string path = request.substr(first_space+1, second_space-first_space-1);

    cout<<"Received "<<method<< " request for " <<path<<endl;
    if(method == "GET") {
        //simulate heavy task with delay
        chrono::system_clock::time_point delay_time = chrono::system_clock::now() + chrono::seconds(3);
        while(delay_time > (chrono::system_clock::now())) {}
        cout<<"Done delay!"<<endl;
        string response = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<html><body><h1>Hello World!</h1></body></html>";
        send(client_socket,response.c_str(),response.length(),0);
    } else {
        std::string response = "HTTP/1.1 404 Not Found\r\nContent-Type: text/html\r\n\r\n<html><body><h1>404 Not Found</h1></body></html>";
        send(client_socket, response.c_str(), response.length(), 0);
    }

    closesocket(client_socket);
    return 0;
}

如果我向服务器发出 3 个 GET 请求,第一个请求将需要 3 秒,第二个请求需要 6 秒,第三个请求需要 9 秒。难道不应该 thread 单独处理连接吗?为什么另一个线程仍然依赖于第一个连接?任何建议都将不胜感激

帖子版权声明 1、本帖标题:C++ 中的套接字:处理 Windows 操作系统中的多个并发请求
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由Matthias Auswöger在本站《sockets》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 首先,由于您没有正确接收和解析 HTTP 请求,因此此代码根本无法成为可行的 HTTP 服务器。

    但是,除此之外,尽管您可以处理多个连接(尽管使用 分离 线程值得怀疑),但 HTTP 1.x 连接根本无法一次处理超过 1 个请求。这就是 HTTP 协议的工作方式,至少在具有多路复用功能的 HTTP/2 之前是这样的。对于 HTTP 1.x,要并行运行多个请求,您需要多个连接,但浏览器往往会池化它们的连接,并且不能保证一次使用多个连接到同一服务器,并且您不能强迫浏览器这样做。

    还有一点需要考虑 - 即使您确实同时有多个连接,您的客户端线程也会有一个繁忙的循环,不会为其他线程提供 CPU 时间。您应该使用 std::this_thread::sleep_for() or std::this_thread::sleep_until() 来使调用线程进入睡眠状态,同时允许其他线程有机会运行,例如:

    if(method == "GET") {
        //simulate heavy task with delay
        std::this_thread::sleep_for(chrono::seconds(3));
        ...
    }
    
返回
作者最近主题: