简单的HTTP客户端c recv()块

时间:2016-05-02 16:42:52

标签: c http client blocking recv

我尝试用c编写简单的HTTP客户端, 当我执行我的程序时,我有时间从网站获取数据。 要特定的recv()块,以及连接关闭。 什么是处理这个问题的最佳方法?我仍想获得网站数据。

ZeroMemory( &hints, sizeof(hints) );
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
// Resolve the server address and port
if (iResult = getaddrinfo(s1, "http", &hints, &result)) {
    printf("getaddrinfo failed with error: %d\n", iResult);
    WSACleanup();
    return 1;
}
// Attempt to connect to an address until one succeeds

for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) {

    // Create a SOCKET for connecting to server
    ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, 
        ptr->ai_protocol);
    if (ConnectSocket == INVALID_SOCKET) {
        printf("socket failed with error: %ld\n", WSAGetLastError());
        WSACleanup();
        return 1;
    }


    iResult = connect( ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
    if (iResult == SOCKET_ERROR) {
        closesocket(ConnectSocket);
        ConnectSocket = INVALID_SOCKET;
        continue;
    }
    break;
}

freeaddrinfo(result);

if (ConnectSocket == INVALID_SOCKET) {
    printf("Unable to connect to server!\n");
    WSACleanup();
    return 1;
}


// Send an initial buffer
iResult = send( ConnectSocket, sendbuf, (int)strlen(sendbuf), 0 );
if (iResult == SOCKET_ERROR) {
    printf("send failed with error: %d\n", WSAGetLastError());
    closesocket(ConnectSocket);
    WSACleanup();
    return 1;
}

// shutdown the connection since no more data will be sent
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
    printf("shutdown failed with error: %d\n", WSAGetLastError());
    closesocket(ConnectSocket);
    WSACleanup();
    return 1;
}

// Receive until the peer closes the connection

do {        
    iResult = recv(ConnectSocket, recvbuf, recvbuflen-1, 0);
    if ( iResult > 0 ) {
         flag = 1;
         recvbuf[iResult] = '\0';
         printf("%s\n",recvbuf);
    }
    else if ( iResult == 0 ) {
            if(!flag) { 
                printf("conection close before recv data\n");
            } else {
                printf("conection close\n");
                break;
            }
    }
    else {
        printf("recv failed with error: %d\n", WSAGetLastError());
    }
} while(iResult>1);


// cleanup
closesocket(ConnectSocket);
WSACleanup();

return 0;

}

我已经使用了HTTP协议概念并发送到我在这个模板中尝试过的每个网址:sendbuf =“GET / [url path] HTTP 1.0 / r / nHost:[www.pure_url.com] / r / n / R / N“

编辑:我已经尝试过[DaSourcerer建议],改为HTTP / 1.1并添加了Connection:close,有时候我得到的数据有时没有。

我还补充道:

int tcp_timeout=10000;
unsigned int  sz = sizeof(tcp_timeout);
setsockopt(ConnectSocket, SOL_SOCKET, SO_RCVTIMEO,
(char*)&tcp_timeout, sz); 

这个想法没有帮助。

1 个答案:

答案 0 :(得分:0)

我认为你的超时太严格了。您发送的标头也会激发服务器等待进一步输入。试试这个:

GET /path HTTP/1.1
Host: example.com
Connection: close

还提到Host是HTTP / 1.1中引入的标头。它在HTTP / 1.0中没有任何意义。您可能也对RFC 7230, section 3.3.3感兴趣,因为您几乎肯定会遇到HTTP / 1.1中的块编码消息。不过不用担心:它可以用简单的状态机解析。