2012-11-16 31 views
0

爲什麼我的代碼只下載半個網頁?有時它下載4x的網頁大小:S套接字下載太少或太多的網頁

我找不到這是什麼問題,這就是爲什麼我問。基本上,我連接到套接字,發送我的請求並讀取響應緩衝區。我試着將它保存到一個文件並將其打印到屏幕上,但它會打印並保存不完整的數據或太多的數據。我不確定是否它的緩衝區溢出或者我做錯了什麼。

任何想法?

#define _WIN32_WINNT 0x501 

#include <iostream> 
#include <winsock2.h> 
#include <ws2tcpip.h> 
#include <stdio.h> 
#include <fstream> 

using namespace std; 

void Get(string WebPage) 
{ 
    WSADATA wsaData; 
    string Address; 
    struct addrinfo *result; 
    struct sockaddr_in *sockaddr_ipv4; 

    char Buffer[50000] = {0}; 

    string Header = "GET/HTTP/1.1\r\n"; 
    Header += "Host: " + WebPage + "\r\n"; 
    Header += "Connection: close\r\n"; 
    Header += "\r\n"; 

    if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) return; 

    SOCKET Socket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); 

    getaddrinfo(WebPage.c_str(), NULL, NULL, &result); 
    if (result->ai_family == AF_INET) 
    { 
     sockaddr_ipv4 = (struct sockaddr_in *) result->ai_addr; 
     Address = inet_ntoa(sockaddr_ipv4->sin_addr); 
    } 
    freeaddrinfo(result); 


    SOCKADDR_IN SockAddr; 
    memset(&SockAddr, 0, sizeof(SockAddr)); 
    SockAddr.sin_port = htons(80); 
    SockAddr.sin_family = AF_INET; 
    SockAddr.sin_addr.s_addr = inet_addr(Address.c_str()); 

    if(connect(Socket,(SOCKADDR*)(&SockAddr),sizeof(SockAddr)) == SOCKET_ERROR) return; 

    if (send(Socket, Header.c_str(), Header.size(), 0) == SOCKET_ERROR) return; 
    shutdown(Socket, SD_SEND); 

    std::string Response; 

    while(true) 
    { 
     int Val = recv(Socket, Buffer, sizeof(Buffer), 0); 
     if (Val == 0) 
      break; 
     else if (Val == SOCKET_ERROR) 
     { 
      cout<<"Error!"; 
     } 
     else 
     { 
      Response += Buffer; 
     } 
    } 

    closesocket(Socket); 
    WSACleanup(); 

    ofstream File; 
    File.open("C:/Saved.html"); 
    File<<Response; 
    File.close(); 
} 

int main() 
{ 
    Get("villavu.com"); 
} 

回答

3

編輯:recv不是null爲你終止數據 - 你需要寫出你收到多少數據,而不僅僅是+ =它。


是否有您迴應任何二進制數據?如果是這樣,

Response += Buffer; 

將停在第一個空字符。我會用一個載體來存儲數據從recv的這樣:

vector<char> recvBuffer(50000); 

int bytesReceived = recv(socket, recvBuffer.data(), recvBuffer.size(), 0); 
//error checking 
recvBuffer.resize(bytesReceived); 

,並再次將接收到的數據存儲在另一個載體,複製它放回

vector<char> pageContents; 

pageContents.insert(pageContents.end(), recvBuffer.begin(), recvBuffer.end()); 

這不能解釋你的4倍數據。

我看到的另一個問題是,在使用緩衝區之後,您並未清零您的緩衝區。

IOW:您需要寫出您接收的數據量,而不僅僅是+ =數組。

+0

啊,這工作。它也修復了4倍數據。 所有我不得不補充的是: Buffer [Val] ='\ 0'; 但我最終改變它像一個你建議的載體。謝謝。 現在唯一的問題是,它有時會爲文件添加額外的符號或數字。我猜想它是以塊的形式下載頁面的,而且可能是塊的長度。不知道如何阻止。 – Brandon

+0

如果你打算解析HTTP響應,你會想要仔細看看這個規範。 –

+0

+1,但沒有必要「清零」整個緩衝區,或者使用2個向量。你可以在循環之前使用'int len = 0;'然後'recvBuffer.resize(len + 50000); int bytesReceived = recv(socket,&recvBuffer [0] + len,recvBuffer.size() - len,0); (注意'data()'僅在C++ 1x中引入;'&recvBuffer [0] + len'保證可以在C++ 03和C++ 1x中工作) 。 –