C++ Проблемы с запросом HTTP GET?

Я написал программу, которая отправляет запрос tcp на веб-адрес, указанный в командной строке, и печатает ответ. Когда я отправляю этот запрос на www.google.co.uk (или любой другой веб-сайт), я ничего не получаю в ответ :(

Может ли кто-нибудь сказать мне, что я делаю неправильно, а также как должен выглядеть правильный GET-запрос к Google. Вот код...

#include <WinSock2.h>
#include <WS2tcpip.h>
#include <stdio.h>

#pragma comment(lib, "Ws2_32.lib")

int main(int argc, char *argv[]){

WSADATA wsaData;
int iResult;

//Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if(iResult != 0){
    printf("WSAStartup failed: %d\n", iResult);
    return 1;
}

struct addrinfo *result = NULL,
                *ptr = NULL,
                hints;

ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;

#define DEFAULT_PORT "80"

//Resolve the server address and port
iResult = getaddrinfo(argv[1], DEFAULT_PORT, &hints, &result);
if(iResult != 0){
    printf("getaddrinfo failed: %d\n", iResult);
    WSACleanup();
    return 1;
}

SOCKET ConnectSocket = INVALID_SOCKET;

//Attempt to connect to the first address returned by
//the call to getaddrinfo
ptr = result;

//Create a SOCKET for connecting to server
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype,
    ptr->ai_protocol);

if(ConnectSocket == INVALID_SOCKET){
    printf("Error at socket(): %ld\n", WSAGetLastError());
    freeaddrinfo(result);
    WSACleanup();
    return 1;
}

//Connect to server
iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
if(iResult == SOCKET_ERROR){
    closesocket(ConnectSocket);
    ConnectSocket = INVALID_SOCKET;
}

//Should really try the next address returned by getaddrinfo
//if the connect call failed
//But for this simple example we just free the resources
//returned by getaddrinfo and print an error message

freeaddrinfo(result);

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

#define DEFAULT_BUFLEN 512

int recvbuflen = DEFAULT_BUFLEN;

char *sendbuf = "GET /index.html HTTP/1.1\r\n";
char recvbuf[DEFAULT_BUFLEN];

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

printf("Bytes Sent: %ld\n", iResult);

//shutdown the connection for sending since no more data will be sent
//the client can still use the ConenctSocket for receiving data
iResult = shutdown(ConnectSocket, SD_SEND);
if(iResult == SOCKET_ERROR){
    printf("shutdown failed: %d\n", WSAGetLastError());
    closesocket(ConnectSocket);
    WSACleanup();
    return 1;
}

do {
    iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
    if(iResult > 0){
        printf("Bytes received: %d\n", iResult);
        printf(recvbuf);
        printf("\n\n");
    } else if(iResult == 0){
        printf("Connection closed\n");
    } else {
        printf("recv failed: %d\n", WSAGetLastError());
    }
} while(iResult > 0);

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

return 0;
 }

Заранее спасибо.


person brnby    schedule 10.07.2012    source источник
comment
Вы пробовали попасть без запроса на страницу? Мне просто интересно, потому что как узнать, является ли страница индекса index.html или index.html или даже home.html и т. д. и т. д.? Поэтому я бы попробовал запрос типа GET HTTP/1.1. А почему вы закрываете соединение до получения ответа?   -  person Vite Falcon    schedule 10.07.2012
comment
Что значит ничего не вернуть? Вы получаете 0 полученных байтов, ваша программа зависает или внезапно завершается, ничего не печатая!?   -  person André Caron    schedule 10.07.2012
comment
@ViteFalcon: это не имеет значения. Если URL-адрес недействителен, сервер все равно отправит правильный HTTP-ответ (перенаправление, страница не найдена и т. д.).   -  person André Caron    schedule 10.07.2012


Ответы (1)


Одна из возможных причин заключается в том, что сервер ожидает больше данных перед отправкой ответа.

char *sendbuf = "GET /index.html HTTP/1.1\r\n";

Это наверное должно быть

char *sendbuf = "GET /index.html HTTP/1.1\r\n\r\n";

таким образом, вы говорите серверу не ожидать больше заголовков HTTP (за каждым заголовком следует \r\n, затем добавляется дополнительный \r\n для завершения запроса).

По сути, ваш HTTP-запрос неполный. Необходимо указать как минимум еще один заголовок (Host). Обратите внимание, что сервер может (неправильно) принять и не завершить запрос в любом случае. Если вы хотите начать с простого, скопируйте запрос, отправленный вашим браузером (например, откройте веб-отладчик и просмотрите исходящие сетевые запросы).

person André Caron    schedule 10.07.2012
comment
Он будет ожидать большего, чем это. Запрос HTTP 1.1 ТРЕБУЕТСЯ также включать заголовок Host, например: char *sendbug = "GET /index.html HTTP/1.1\r\nHost: TheServerHostNameHere\r\n\r\n"; - person Remy Lebeau; 10.07.2012