Получение случайных/странных данных с помощью Winsock

Я новичок в использовании Winsock, и чтобы посмотреть, что он может сделать, я сделал быстрый HTTP-клиент (не совсем), который просто запрашивал индексную страницу веб-сайта. Однако при попытке прочитать данные, полученные с сервера, это не то, что я ожидал. Вот пример вывода:

ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ̤÷

Это происходит при попытке подключения к любому веб-сайту, и я получаю это от попытки вывести содержимое recvbuf, где предполагается хранить полученные данные. Это то, как данные обычно возвращаются из winsock? Кроме того, я не думаю, что это мой код, потому что я не получаю никаких ошибок. Я почти уверен, что это нормально, и я просто пропустил шаг, но поиск ничего не дал, поэтому я спрашиваю здесь.

РЕДАКТИРОВАТЬ: Извините, не могу поверить, что забыл свой код:

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include "stdafx.h"
#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
#include <iostream>

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

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    addrinfo *result, *ptr, hints;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;

WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
iResult = getaddrinfo("google.com", "80", &hints, &result);
if (iResult != 0) {
    cout << "Error in getaddrinfo()!\n";
    cin.get();
    return 1;
} else {
    cout << "Success!\n";
}

SOCKET ConnectSocket = INVALID_SOCKET;

ptr = result;

ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);

iResult = connect(ConnectSocket, ptr->ai_addr, int(ptr->ai_addrlen));

freeaddrinfo(result);

int recvbuflen = 512;
char *sendbuf = "GET / http/1.1";
char recvbuf[512];

send(ConnectSocket, sendbuf, (int)strlen(sendbuf), 0);

shutdown(ConnectSocket, SD_SEND);

do {
    iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
    cout << recvbuf << endl;
} while (iResult > 0);

cin.get();
return 0;
}

person diodepain    schedule 31.05.2014    source источник
comment
Мой хрустальный шар говорит, что ошибка в строке 42.   -  person Jerry Coffin    schedule 01.06.2014
comment
Какие данные вы ожидаете получить? cout ожидает строку ASCII с нулевым завершением.   -  person ScottMcP-MVP    schedule 01.06.2014
comment
Я думал, что верну нормальный HTML-код. Извините, если это несколько глупо ожидать, но я полный нуб в winsock.   -  person diodepain    schedule 01.06.2014
comment
вздыхает. Перед печатью буфера проверьте значение, возвращаемое recv.   -  person Captain Obvlious    schedule 01.06.2014
comment
@CaptainObvlious, после проверки кажется, что соединение немедленно закрывается. Я почти уверен, что ничего не получаю от сервера.   -  person diodepain    schedule 01.06.2014
comment
Запрос недействителен, используйте вместо него char *sendbuf = "GET / HTTP/1.1\r\n\r\n";. Обратите внимание на использование заглавных букв в слове HTTP и обязательные конечные пары CRLF.   -  person Retired Ninja    schedule 01.06.2014
comment
Вам также нужен заголовок Host, он требуется для HTTP 1.1.   -  person Remy Lebeau    schedule 01.06.2014


Ответы (2)


Ваш HTTP-запрос ошибочен. Прочтите RFC 2616. Попробуйте это вместо этого:

char *sendbuf = "GET / HTTP/1.1\r\nHost: google.com\r\n\r\n";

Это абсолютный минимум, необходимый для запроса HTTP 1.1.

Поскольку вы закрываете отправляющую часть своего сокета, вы также должны включить заголовок Connection: close, поскольку вы не будете повторно использовать сокет для последующих запросов:

char *sendbuf = "GET / HTTP/1.1\r\nHost: google.com\r\nConnection: close\r\n\r\n";

Если вместо этого вы отправляете запрос HTTP 1.0, вы можете опустить заголовки Host и Connection (Host не используется в версии 1.0, а close используется по умолчанию в версии 1.0):

char *sendbuf = "GET / HTTP/1.0\r\n\r\n";

При этом ваш цикл чтения слишком прост, это не то, как следует читать ответы HTTP. Вам нужно читать заголовки HTTP построчно, пока не встретите пустую строку, затем проанализировать заголовки и прочитать остальную часть тела HTTP, если таковая имеется, в зависимости от того, как заголовки говорят вам читать (см. RFC 2616, раздел 4.4 для получения подробной информации). См. другой ответ, который я написал для правильного рабочего процесса.

person Remy Lebeau    schedule 01.06.2014

Я мало знаю о "GET/http/1.1", но Google использует HTTPS.

Поэтому я заменяю «google.com» на «web.mit.edu» и перехожу к обновлению «http://web.mit.edu/".

И это действительно работает.

person loverszhaokai    schedule 01.06.2014
comment
Google в основном использует HTTPS, но он будет реагировать на HTTP и перенаправлять на HTTPS по мере необходимости. - person Remy Lebeau; 01.06.2014
comment
Но я потерпел неудачу с google.com, который на самом деле является https://www.google.com, а на смену ему пришел web.mit.edu. - person loverszhaokai; 03.06.2014