有什么方法可以简单地用c++发出HTTP请求吗?具体来说,我想下载一个页面(一个API)的内容,并检查内容,看看它是否包含1或0。是否也可以将内容下载到字符串中?
当前回答
你可以使用embeddedRest库。它是一个轻量级的头文件库。所以很容易将它包含到你的项目中,它不需要编译,因为里面没有。cpp文件。
从自述文件中请求示例。Md from repo:
#include "UrlRequest.hpp"
//...
UrlRequest request;
request.host("api.vk.com");
const auto countryId = 1;
const auto count = 1000;
request.uri("/method/database.getCities",{
{ "lang", "ru" },
{ "country_id", countryId },
{ "count", count },
{ "need_all", "1" },
});
request.addHeader("Content-Type: application/json");
auto response = std::move(request.perform());
if (response.statusCode() == 200) {
cout << "status code = " << response.statusCode() << ", body = *" << response.body() << "*" << endl;
}else{
cout << "status code = " << response.statusCode() << ", description = " << response.statusDescription() << endl;
}
其他回答
对于这个答案,我参考了Software_Developer的答案。通过重新构建代码,我发现一些部分已弃用(gethostbyname())或不为操作提供错误处理(创建套接字,发送一些东西)。
下面的windows代码是用Visual Studio 2013和windows 8.1 64位以及windows 7 64位进行测试的。它将目标与www.google.com的Web服务器的IPv4 TCP连接。
#include <winsock2.h>
#include <WS2tcpip.h>
#include <windows.h>
#include <iostream>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
int main (){
// Initialize Dependencies to the Windows Socket.
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) {
cout << "WSAStartup failed.\n";
system("pause");
return -1;
}
// We first prepare some "hints" for the "getaddrinfo" function
// to tell it, that we are looking for a IPv4 TCP Connection.
struct addrinfo hints;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET; // We are targeting IPv4
hints.ai_protocol = IPPROTO_TCP; // We are targeting TCP
hints.ai_socktype = SOCK_STREAM; // We are targeting TCP so its SOCK_STREAM
// Aquiring of the IPv4 address of a host using the newer
// "getaddrinfo" function which outdated "gethostbyname".
// It will search for IPv4 addresses using the TCP-Protocol.
struct addrinfo* targetAdressInfo = NULL;
DWORD getAddrRes = getaddrinfo("www.google.com", NULL, &hints, &targetAdressInfo);
if (getAddrRes != 0 || targetAdressInfo == NULL)
{
cout << "Could not resolve the Host Name" << endl;
system("pause");
WSACleanup();
return -1;
}
// Create the Socket Address Informations, using IPv4
// We dont have to take care of sin_zero, it is only used to extend the length of SOCKADDR_IN to the size of SOCKADDR
SOCKADDR_IN sockAddr;
sockAddr.sin_addr = ((struct sockaddr_in*) targetAdressInfo->ai_addr)->sin_addr; // The IPv4 Address from the Address Resolution Result
sockAddr.sin_family = AF_INET; // IPv4
sockAddr.sin_port = htons(80); // HTTP Port: 80
// We have to free the Address-Information from getaddrinfo again
freeaddrinfo(targetAdressInfo);
// Creation of a socket for the communication with the Web Server,
// using IPv4 and the TCP-Protocol
SOCKET webSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (webSocket == INVALID_SOCKET)
{
cout << "Creation of the Socket Failed" << endl;
system("pause");
WSACleanup();
return -1;
}
// Establishing a connection to the web Socket
cout << "Connecting...\n";
if(connect(webSocket, (SOCKADDR*)&sockAddr, sizeof(sockAddr)) != 0)
{
cout << "Could not connect";
system("pause");
closesocket(webSocket);
WSACleanup();
return -1;
}
cout << "Connected.\n";
// Sending a HTTP-GET-Request to the Web Server
const char* httpRequest = "GET / HTTP/1.1\r\nHost: www.google.com\r\nConnection: close\r\n\r\n";
int sentBytes = send(webSocket, httpRequest, strlen(httpRequest),0);
if (sentBytes < strlen(httpRequest) || sentBytes == SOCKET_ERROR)
{
cout << "Could not send the request to the Server" << endl;
system("pause");
closesocket(webSocket);
WSACleanup();
return -1;
}
// Receiving and Displaying an answer from the Web Server
char buffer[10000];
ZeroMemory(buffer, sizeof(buffer));
int dataLen;
while ((dataLen = recv(webSocket, buffer, sizeof(buffer), 0) > 0))
{
int i = 0;
while (buffer[i] >= 32 || buffer[i] == '\n' || buffer[i] == '\r') {
cout << buffer[i];
i += 1;
}
}
// Cleaning up Windows Socket Dependencies
closesocket(webSocket);
WSACleanup();
system("pause");
return 0;
}
引用:
弃用gethostbyname
socket()的返回值
send()的返回值
虽然有点晚了。你可能更喜欢https://github.com/Taymindis/backcurl。
它允许你在移动c++开发上进行http调用。适合手机游戏开发
bcl::init(); // init when using
bcl::execute<std::string>([&](bcl::Request *req) {
bcl::setOpts(req, CURLOPT_URL , "http://www.google.com",
CURLOPT_FOLLOWLOCATION, 1L,
CURLOPT_WRITEFUNCTION, &bcl::writeContentCallback,
CURLOPT_WRITEDATA, req->dataPtr,
CURLOPT_USERAGENT, "libcurl-agent/1.0",
CURLOPT_RANGE, "0-200000"
);
}, [&](bcl::Response * resp) {
std::string ret = std::string(resp->getBody<std::string>()->c_str());
printf("Sync === %s\n", ret.c_str());
});
bcl::cleanUp(); // clean up when no more using
有什么方法可以简单地用c++发出HTTP请求吗?具体来说,我想下载一个页面(一个API)的内容,并检查内容,看看它是否包含1或0。是否也可以将内容下载到字符串中?
首先……我知道这个问题已经有12年了。然而。没有一个答案给出的例子是“简单的”,不需要构建一些外部库
下面是我能想到的检索和打印网页内容的最简单的解决方案。
关于下面示例中使用的函数的一些文档
// wininet lib : https://learn.microsoft.com/en-us/windows/win32/api/wininet/ // wininet->internetopena(); https://learn.microsoft.com/en-us/windows/win32/api/wininet/nf-wininet-internetopena // wininet->intenetopenurla(); https://learn.microsoft.com/en-us/windows/win32/api/wininet/nf-wininet-internetopenurla // wininet->internetreadfile(); https://learn.microsoft.com/en-us/windows/win32/api/wininet/nf-wininet-internetreadfile // wininet->internetclosehandle(); https://learn.microsoft.com/en-us/windows/win32/api/wininet/nf-wininet-internetclosehandle
#include <iostream>
#include <WinSock2.h>
#include <wininet.h>
#pragma comment(lib, "wininet.lib")
int main()
{
// ESTABLISH SOME LOOSE VARIABLES
const int size = 4096;
char buf[size];
DWORD length;
// ESTABLISH CONNECTION TO THE INTERNET
HINTERNET internet = InternetOpenA("Mozilla/5.0", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, NULL);
if (!internet)
ExitProcess(EXIT_FAILURE); // Failed to establish connection to internet, Exit
// ATTEMPT TO CONNECT TO WEBSITE "google.com"
HINTERNET response = InternetOpenUrlA(internet, "http://www.google.com", NULL, NULL, NULL, NULL);
if (!response) {
// CONNECTION TO "google.com" FAILED
InternetCloseHandle(internet); // Close handle to internet
ExitProcess(EXIT_FAILURE);
}
// READ CONTENTS OF WEBPAGE IN HTML FORMAT
if (!InternetReadFile(response, buf, size, &length)) {
// FAILED TO READ CONTENTS OF WEBPAGE
// Close handles and Exit
InternetCloseHandle(response); // Close handle to response
InternetCloseHandle(internet); // Close handle to internet
ExitProcess(EXIT_FAILURE);
}
// CLOSE HANDLES AND OUTPUT CONTENTS OF WEBPAGE
InternetCloseHandle(response); // Close handle to response
InternetCloseHandle(internet); // Close handle to internet
std::cout << buf << std::endl;
return 0;
}
注意,这并不需要libcurl, Windows.h,或WinSock!没有编译库,没有项目配置,等等。我有这段代码在Windows 10上的Visual Studio 2017 c++中工作:
#pragma comment(lib, "urlmon.lib")
#include <urlmon.h>
#include <sstream>
using namespace std;
...
IStream* stream;
//Also works with https URL's - unsure about the extent of SSL support though.
HRESULT result = URLOpenBlockingStream(0, "http://google.com", &stream, 0, 0);
if (result != 0)
{
return 1;
}
char buffer[100];
unsigned long bytesRead;
stringstream ss;
stream->Read(buffer, 100, &bytesRead);
while (bytesRead > 0U)
{
ss.write(buffer, (long long)bytesRead);
stream->Read(buffer, 100, &bytesRead);
}
stream->Release();
string resultString = ss.str();
我只是想出了如何做到这一点,因为我想要一个简单的API访问脚本,像libcurl这样的库给我带来了各种各样的问题(即使我遵循了说明……),而WinSock只是太低级和复杂了。
我不太确定所有的IStream读取代码(特别是while条件-请随意纠正/改进),但嘿,它工作,麻烦!(这对我来说是有意义的,因为我使用了一个阻塞(同步)调用,这是很好的,bytesRead将始终是> 0U,直到流(ISequentialStream?)完成读取,但谁知道呢。)
请参见:URL名称和异步可插协议参考
如果您正在寻找在多个平台(Linux, Windows和Mac)支持的c++中的HTTP客户端库,以使用Restful web服务。您可以有以下选项。
QT网络库-允许应用程序发送网络请求并接收回复 c++ REST SDK -一个新兴的支持PPL的第三方HTTP库 Libcurl -它可能是本地世界中使用最多的http库之一。