我用c++编写了HTTP客户端,以便在后台下载文件,并且它能勤奋地工作,但是当我下载通常不会损坏的pdf时,它会损坏。
有一些类似libcurl poco的库,但是由于我想了解基础知识,所以我写了纯套接字代码。我看了库的源代码(例如curl),但是我对它们一无所知。
file.pdf地址:https://www.axmag.com/download/pdfurl-guide.pdf
这是我的代码:
#include <iostream>
#include <stdio.h>
#include <WS2tcpip.h>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
void main()
{
setlocale(LC_ALL,
"Turkish");
WSADATA wsdata;
WORD ver = MAKEWORD(2, 2);
int ws0k = WSAStartup(ver, &wsdata);
if (ws0k != 0) {
return;
}// classic startup operations
SOCKET client = socket(AF_INET, SOCK_STREAM, 0);
if (client == INVALID_SOCKET) {
return;
}
else {
cout << "Soket oluşturuldu." << endl; // successfully created socket
}
struct hostent* host;
host = gethostbyname("www.axmag.com");
sockaddr_in target;
target.sin_addr.S_un.S_addr = *((unsigned long*)host->h_addr); //WEBSITE ADDRESS
target.sin_port = htons(80); // HTTP PORT : 80
target.sin_family = AF_INET; // I don't know the address family of http.
int conn = connect(client, (sockaddr*)&target, sizeof(target));
if (conn < 0) {
return;
}
else {
cout << "Bağlantı isteği başarılı." << endl; // successfully connected.
}
char HTTP_MESSAGE[] = "GET /download/pdfurl-guide.pdf HTTP/1.0\r\nHost: www.axmag.com\r\nConnection: close\r\n\r\n";
if (send(client, HTTP_MESSAGE, sizeof(HTTP_MESSAGE), 0) < 0) { // send http request.
return;
}
else {
cout << "Komut başarıyla gönderildi." << endl; // Successfully send http request.
}
FILE* file = NULL; // file
file = fopen("C:\\Users\\user\\Desktop\\test.pdf", "wb"); //Create file
if (file == NULL) {
return;
}
else {
cout << "Dosya oluşturuldu." << endl; //Successfully created file.
}
char recvbuf[1024];
int received;
while (received = recv(client, recvbuf, sizeof(recvbuf), 0) > 0) { // RECV
cout << recvbuf << endl;
fwrite(recvbuf, 1, received, file); // write data to file
}
fclose(file);
closesocket(client);
WSACleanup();
system("pause");
}
我下载成功了。问题出在fwrite函数上。
我将ElementSize参数更改为缓冲区的值,并且它发生了。
解决方案代码:
char recvbuf[64];
int received;
while (received = recv(client, recvbuf, sizeof(recvbuf), 0) > 0) { // RECV
cout << recvbuf << endl;
fwrite(recvbuf, 64, received, file); // write data to file
}
最佳答案
一旦出现问题,那就是>
的运算符优先级高于=
的运算符优先级,因此您的received
变量将获得0
或1
。您可以使用一组额外的括号来解决此问题:
while ((received = recv(client, recvbuf, sizeof(recvbuf), 0)) > 0) {
...
当Web服务器发回其响应时,响应将包括HTTP响应 header 。您需要读取此响应头并将其保留在文件之外。
简单地说,
// Skip the HTTP header
std::string http_resp;
auto eoh = std::string::npos;
while ((received = recv(client, recvbuf, sizeof(recvbuf), 0)) > 0) {
http_resp.append(recvbuf, received);
auto eoh = http_resp.find("\r\n\r\n");
if (eoh != std::string::npos) {
if ((eoh + 4) < http_resp.size()) {
auto rest = http_resp.substr(eoh + 4);
fwrite(rest.c_str(), 1, rest.size(), file);
}
break;
}
}
// Get the rest of the file
if (received > 0) {
while ((received = recv(client, recvbuf, sizeof(recvbuf), 0)) > 0) {
fwrite(recvbuf, 1 ,received, file);
}
}
关于c++ - C++ HTTP客户端recv()和写入文件问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59686010/