好吧,所以当我第一次开始时,我实际上是在下载实际的文件大小,但现在却没有。我有更多字符串的原因是我可以创建一个子字符串,然后删除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;
}
答案 0 :(得分:1)
问题与Winsock无关,而是误用C ++字符串。 (请注意,我没有用精细的牙齿或其他任何东西完成其余的代码,也可能有其他问题。但这是一个突出的。)
当你说recvBufferTest = recvBuffer
你正在使用等号运算符as described here的第二种形式时,
指向以null结尾字符序列的指针。序列将被复制为字符串的新值。
[强调我的。]
因此,对于您获得的每个数据块,您要设置recvBufferTest
以包含最多但不包括第一个空字符的字节,并丢弃其余的字符。由于您正在下载可执行文件,因此零字节将非常常见,因此您将丢弃大部分内容。
相反,如果一个数据块恰好不包含零字节,recvBufferTest
将包括内存中跟随recvBuffer
的任何内存内容,最多但不包括第一个零字节。因此,如果您要下载文本文件,您可能会发现它更长而不是预期。
相反,您需要使用允许您指定数据缓冲区长度的结构。例如,你可以说像
这样的东西recvBufferTest.assign(recvBuffer, ReturnStuff);