Winsock 2 Чтение текста с URL
Например, вот что я хочу сделать:
if (http->Connect("http://pastebin.com/raw/9uL16CyN"))
{
YString data = "";
if (http->ReceiveData(data))
{
std::cout << "Networked data: " << std::endl;
std::cout << data << std::endl;
}
else
std::cout << "Failed to connect to internet.\n";
}
Страница, с которой я пытаюсь прочитать, является необработанным текстом ASCII ( http://pastebin.com/raw/9uL16CyN)
Я надеялся, что это сработает легко, но, очевидно, нет, я продолжаю получать ошибку WSA: WSAHOST_NOT_FOUND (11001)
Функция My Connect:
bool Http::Connect(YString addr)
{
_socket = Network::CreateConnectSocket(addr, 53); // 53 is the port
return _socket != INVALID_SOCKET;
}
Функция CreateConnectSocket:
int iResult;
SOCKET ConnectSocket = INVALID_SOCKET;
// holds address info for socket to connect to
struct addrinfo *result = NULL,
*ptr = NULL,
hints;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP; //TCP connection!!!
//resolve server address and port
iResult = getaddrinfo(addr.c_str(), std::to_string(port).c_str(), &hints, &result);
if (iResult != 0)
{
printf("Network::CreateSocket failed with %s as addr, and %i as port.\nError code: %i.\n", (char*)addr.c_str(), port, iResult);
return INVALID_SOCKET;
}
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("Network::CreateSocket failed with error: %ld\n", WSAGetLastError());
return INVALID_SOCKET;
}
// Connect to server.
iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (iResult == SOCKET_ERROR)
{
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
printf("Network::CreateSocket failed the server is down... did not connect.\n");
}
}
freeaddrinfo(result);
if (ConnectSocket == INVALID_SOCKET)
{
printf("Network::CreateSocket failed.\n");
return INVALID_SOCKET;
}
u_long iMode = 1;
iResult = ioctlsocket(ConnectSocket, FIONBIO, &iMode);
if (iResult == SOCKET_ERROR)
{
printf("Network::CreateSocket ioctlsocket failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
return INVALID_SOCKET;
}
char value = 1;
setsockopt(ConnectSocket, IPPROTO_TCP, TCP_NODELAY, &value, sizeof(value));
return ConnectSocket;
Большая часть его взята из существующих источников.
1 ответ
Ваш звонок в Connect()
неправильно. Вы не можете передать полный URL getaddrinfo()
, Вам нужно передать только доменное имя и номер порта самостоятельно. Кстати, порт HTTP 80, а не 53.
Кроме того, вы не отправляете HTTP GET
запрос к серверу с просьбой выслать вам текстовый документ. HTTP-сервер не отправит ответ, пока вы не отправите запрос первым.
Вам нужно что-то более похожее на это:
bool Http::Connect(YString addr, int port)
{
_socket = Network::CreateConnectSocket(addr, port);
return _socket != INVALID_SOCKET;
}
if (http->Connect("pastebin.com", 80))
{
YString data = "GET /raw/9uL16CyN HTTP/1.1\r\n"
"Host: pastebin.com\r\n"
"Connection: close\r\n"
"\r\n";
if (http->SendData(data))
{
YString data = "";
if (http->ReceiveData(data))
{
std::cout << "Networked data: " << std::endl;
std::cout << data << std::endl;
}
else
std::cout << "Failed to receive data from internet.\n";
}
else
std::cout << "Failed to send request to Pastebin.\n";
}
else
std::cout << "Failed to connect to Pastebin.\n";
При этом вам необходимо учитывать, что сервер собирает данные ответа с заголовками, например:
GET /raw/9uL16CyN HTTP/1.1
Host: pastebin.com
HTTP/1.1 200 OK
Date: Wed, 23 Dec 2015 00:00:01 GMT
Content-Type: text/plain; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Set-Cookie: __cfduid=db6ba4b037d673b67757500aca4e2227b1450828801; expires=Thu, 22-Dec-16 00:00:01 GMT; path=/; domain=.pastebin.com; HttpOnly
X-Powered-By: PHP/5.5.5
Cache-Control: public, max-age=1801
Vary: Accept-Encoding
CF-Cache-Status: HIT
Expires: Wed, 23 Dec 2015 00:30:02 GMT
Server: cloudflare-nginx
CF-RAY: 258fc8a8168a2276-LAX
2a
Text, text, text, text! Some more text! :D
0
Итак, предполагая ReceiveData()
просто возвращает все, что получает, вам придется удалить эти заголовки и отменить chunked
кодирование, прежде чем вы сможете использовать содержимое текстового файла самостоятельно. Пожалуйста, прочтите RFC 2616 (или его преемники RFC 7230-7235), в которых подробно описан протокол HTTP.
При этом вам следует прекратить попытки реализовать HTTP вручную (это более сложно, чем вы думаете) и использовать вместо этого уже существующую библиотеку, так же как libcurl
или даже собственный Microsoft WinInet
или же WinHTTP
API-интерфейсы. Пусть они сделают за вас тяжелую работу.