Bug keep-alive延迟

时间:2017-03-28 07:16:05

标签: c++ sockets keep-alive

此代码使用keep-alive连接以加载许多共享相同IP地址的域,但是在前25个域之后存在一个错误,每个域加载都会延迟30秒!怎么解决这个问题?

#pragma comment(lib,"ws2_32.lib")
#include <WinSock2.h>
#include <iostream>
int main(){
    WSAData wsaData;
    WORD DllVersion = MAKEWORD(2, 1);
    if (WSAStartup(DllVersion, &wsaData) != 0) {
        MessageBoxA(NULL, "Winsock startup failed", "Error", MB_OK | MB_ICONERROR);
        exit(1);
    }
    SOCKADDR_IN addr;
    int sizeofaddr = sizeof(addr);
    addr.sin_addr.s_addr = inet_addr("123.123.123.123");
    addr.sin_port = htons(80);
    addr.sin_family = AF_INET;
    SOCKET Connection = socket(AF_INET, SOCK_STREAM, NULL);
    if (connect(Connection, (SOCKADDR*)&addr, sizeofaddr) != 0)
    {
        MessageBoxA(NULL, "Failed to Connect", "Error", MB_OK | MB_ICONERROR);
        return 0;
    }
    std::cout << "Connected!" << std::endl;
    char MTD[] = "GET / HTTP/1.1\r\nHost:site.com\r\nConnection:keep-alive\r\n\r\nGET / HTTP/1.1\r\nHost:site.com\r\nConnection:keep-alive\r\n\r\nGET / HTTP/1.1\r\nHost:site.com\r\nConnection:keep-alive\r\n\r\nGET / HTTP/1.1\r\nHost:site.com\r\nConnection:keep-alive\r\n\r\nGET / HTTP/1.1\r\nHost:site.com\r\nConnection:keep-alive\r\n\r\nGET / HTTP/1.1\r\nHost:site.com\r\nConnection:keep-alive\r\n\r\nGET / HTTP/1.1\r\nHost:site.com\r\nConnection:keep-alive\r\n\r\nGET / HTTP/1.1\r\nHost:site.com\r\nConnection:keep-alive\r\n\r\nGET / HTTP/1.1\r\nHost:site.com\r\nConnection:keep-alive\r\n\r\nGET / HTTP/1.1\r\nHost:site.com\r\nConnection:close\r\n\r\n";
    send(Connection, MTD, sizeof(MTD), NULL);
    char MOTD[1];
    int result;
    while ((result = recv(Connection, MOTD, 1, NULL)) > 0){
        std::cout << MOTD[0]; // ...
    }
    if (result == 0) {
        // end of stream
        std::cout << "end of stream";
        close(Connection);
    } else if (result < 0) {
        // error
        std::cout << "error";
        perror("recv"); // at least
        close(Connection);
    } else {
        std::cout << "data received";
        // data received, in MOTD[0..result-1]
    }
};

1 个答案:

答案 0 :(得分:2)

result=recv(Connection, MOTD, 1, NULL);
while(recv(Connection, MOTD, 1, NULL)){

这没有任何意义。第一个recv()将至少一个字节读入缓冲区或将result设置为零或-1,然后立即忽略它所做的任何事情并发出另一个recv(),其结果是您忽略的。应该更像这样:

while ((result = recv(Connection, MOTD, 1, NULL)) > 0){
    // data received, in MOTD[0..result-1]
}
if (result == 0) {
    // end of stream
    close(Connection);
} else if (result < 0) {
    // error
    perror("recv"); // at least
    close(Connection);
}

注意:您根本没有使用HTTP keepalive。您正在为每个请求创建一个新套接字,并且永远不会关闭它,至少在您使用此答案中的代码之前。您通过Connection: keepalive标头告诉服务器以保持该连接的活动,这只会浪费服务器资源。正确使用HTTP keep-alive或在每次请求后关闭套接字。