2012-11-16 4 views
0

왜 내 코드는 웹 페이지 절반 만 다운로드합니까? 때로는 웹 페이지 크기의 4 배를 다운로드합니다. 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 is not null for your data - 당신은 + = it뿐만 아니라받은 데이터의 양을 기록해야합니다.


응답에 바이너리 데이터가 있습니까? 그렇다면

Response += Buffer; 

은 첫 번째 null 문자에서 중단됩니다. 나는 등의 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 배 데이터도 수정했습니다. 추가 할 내용은 모두 다음과 같습니다. 버퍼 [Val] = '\ 0'; 하지만 당신이 제안한 것처럼 그것을 벡터로 변경했습니다. 고맙습니다. 지금은 파일에 여분의 기호 나 숫자가 추가되는 경우에만 문제가 발생합니다. 나는 그 페이지를 chunk와 아마 chunk 길이로 다운로드한다고 생각한다. 어떻게 그걸 막을 지 모르겠다. – Brandon

+0

HTTP 응답을 구문 분석하려면 사양을 매우 자세히보고 싶을 것입니다. –

+0

+1하지만 완전한 버퍼를 "제로 아웃"하거나 2 개의 벡터를 사용할 필요는 없습니다. 루프 전에 'int len ​​= 0;'을 사용하고,'recvBuffer.resize (len + 50000); int bytesReceived = recv (소켓, & recvBuffer [0] + len, recvBuffer.size() - len, 0); 'recvBuffer [0] + len'는 C++ 03과 C++ 1x에서 모두 작동한다는 것이 보증되어 있습니다.) 또한 len + = bytesReceived; . –