下载的.exe不完整,C ++ Winsock

时间:2016-01-02 05:38:22

标签: c++ winsock

好吧,所以当我第一次开始时,我实际上是在下载实际的文件大小,但现在却没有。我有更多字符串的原因是我可以创建一个子字符串,然后删除HTML标题(然后写下所有信息)

反正!任何知道WINSOCK的人都可以告诉我这是什么问题吗?我想学习Winsock以了解事物的核心,所以请不要推荐其他API或其他东西。谢谢!

我知道当人们将ofstream :: write添加到他们的while循环时他们使用recv的返回,所以我把它全部添加起来然后放入我的ofstream :: write中,因为我认为它是相同的。 (我没有放在那里因为如上所述,我想删除HTML标题)

#include "stdafx.h"
#include <iostream>
#include <WinSock2.h>
#include <Ws2tcpip.h>
#include <string>
#include <stdio.h>
#include <fstream>
#define BUFFER_LEN 4096

int main()
{
    WSADATA wsaData = { 0 };
    SOCKET ConnectSocket = INVALID_SOCKET;
    addrinfoW *ptr = nullptr, *result = nullptr, hints = { 0 };
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    std::ofstream test;

    try {
        if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
            throw(1);
        }
        if (GetAddrInfoW(L"www.mydati.com", L"80", &hints, &result) != 0) {
            throw(2);
        }

        ptr = result;
        ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
        if (ConnectSocket == INVALID_SOCKET) {
            throw(3);
        }

        if (connect(ConnectSocket, ptr->ai_addr, ptr->ai_addrlen) != 0) {
            throw(4);
        }

        std::string SendBuffer;
        SendBuffer = "GET //download/hss-win2/HSS-773.exe / HTTP/1.1\r\n";
        SendBuffer += "Host: www.mydati.com\r\n\r\n";
        send(ConnectSocket, SendBuffer.c_str(), SendBuffer.length(), 0);

        int ReturnBytes = 0;
        int ReturnStuff = 0;
        std::string recvBufferTest, recvBufferTest2;
        char recvBuffer[BUFFER_LEN] = { 0 };

        test.open("HotSpotShield.txt", std::ofstream::binary);


        while (ReturnStuff = recv(ConnectSocket, recvBuffer, BUFFER_LEN, 0) > 0) {

            ReturnBytes = ReturnBytes + ReturnStuff;
            std::cout << recvBuffer;
            recvBufferTest = recvBuffer;
            recvBufferTest2.append(recvBufferTest);
        }

        int HeaderPosition = 0;
        HeaderPosition = recvBufferTest2.find("\r\n\r\n");
        recvBufferTest = recvBufferTest2.substr(HeaderPosition + 4, std::string::npos);

        test.write(&recvBufferTest[0], ReturnBytes);
        MessageBox(NULL, NULL, NULL, NULL);



    }

    catch (int FailureCode) {
        switch (FailureCode) {

        case 1:{
            MessageBox(NULL, L"WSAStartup was unable to start.", L"Error: 1", MB_OK);
            WSACleanup();
            break;
            }

        case 2: {
            MessageBox(NULL, L"GetAddrInfo did not find match.", L"Error: 2", MB_OK);
            WSACleanup();
            break;
        }

        case 3: {
            MessageBox(NULL, L"ConnectionSocket is empty", L"Error: 3", MB_OK);
            FreeAddrInfoW(result);
            WSACleanup();
            break;
        }

        case 4: {
            MessageBox(NULL, L"You are unable to connect", L"Error: 4", MB_OK);
            FreeAddrInfoW(result);
            closesocket(ConnectSocket);
            WSACleanup();
            break;
        }
        }
    }



    return 0;
}

1 个答案:

答案 0 :(得分:1)

问题与Winsock无关,而是误用C ++字符串。 (请注意,我没有用精细的牙齿或其他任何东西完成其余的代码,也可能有其他问题。但这是一个突出的。)

当你说recvBufferTest = recvBuffer你正在使用等号运算符as described here的第二种形式时,

  

指向以null结尾字符序列的指针。序列将被复制为字符串的新值。

[强调我的。]

因此,对于您获得的每个数据块,您要设置recvBufferTest以包含最多但不包括第一个空字符的字节,并丢弃其余的字符。由于您正在下载可执行文件,因此零字节将非常常见,因此您将丢弃大部分内容。

相反,如果一个数据块恰好不包含零字节,recvBufferTest将包括内存中跟随recvBuffer的任何内存内容,最多但不包括第一个零字节。因此,如果您要下载文本文件,您可能会发现它更长而不是预期。

相反,您需要使用允许您指定数据缓冲区长度的结构。例如,你可以说像

这样的东西
recvBufferTest.assign(recvBuffer, ReturnStuff);