[英]How do you make a HTTP request with C++?
有什么方法可以輕松地用 C++ 發出 HTTP 請求? 具體來說,我想下載頁面(API)的內容並檢查內容是否包含 1 或 0。是否也可以將內容下載到字符串中?
我有同樣的問題。 libcurl真的很完整。 當您要求 C++ 庫時,您可能會對 C++ 包裝器curlpp感興趣。 neon是另一個有趣的 C 庫,它也支持WebDAV 。
如果您使用 C++,curlpp 似乎很自然。 源代碼分發中提供了許多示例。 要獲取 URL 的內容,您可以執行類似的操作(從示例中提取):
// Edit : rewritten for cURLpp 0.7.3
// Note : namespace changed, was cURLpp in 0.7.2 ...
#include <curlpp/cURLpp.hpp>
#include <curlpp/Options.hpp>
// RAII cleanup
curlpp::Cleanup myCleanup;
// Send request and get a result.
// Here I use a shortcut to get it in a string stream ...
std::ostringstream os;
os << curlpp::options::Url(std::string("http://example.com"));
string asAskedInQuestion = os.str();
查看curlpp 源碼分發中的examples
目錄,有很多更復雜的案例,以及使用 curlpp 的簡單完整的最小案例。
我的 2 美分...
窗口代碼:
#include <string.h>
#include <winsock2.h>
#include <windows.h>
#include <iostream>
#include <vector>
#include <locale>
#include <sstream>
using namespace std;
#pragma comment(lib,"ws2_32.lib")
int main( void ){
WSADATA wsaData;
SOCKET Socket;
SOCKADDR_IN SockAddr;
int lineCount=0;
int rowCount=0;
struct hostent *host;
locale local;
char buffer[10000];
int i = 0 ;
int nDataLength;
string website_HTML;
// website url
string url = "www.google.com";
//HTTP GET
string get_http = "GET / HTTP/1.1\r\nHost: " + url + "\r\nConnection: close\r\n\r\n";
if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0){
cout << "WSAStartup failed.\n";
system("pause");
//return 1;
}
Socket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
host = gethostbyname(url.c_str());
SockAddr.sin_port=htons(80);
SockAddr.sin_family=AF_INET;
SockAddr.sin_addr.s_addr = *((unsigned long*)host->h_addr);
if(connect(Socket,(SOCKADDR*)(&SockAddr),sizeof(SockAddr)) != 0){
cout << "Could not connect";
system("pause");
//return 1;
}
// send GET / HTTP
send(Socket,get_http.c_str(), strlen(get_http.c_str()),0 );
// recieve html
while ((nDataLength = recv(Socket,buffer,10000,0)) > 0){
int i = 0;
while (buffer[i] >= 32 || buffer[i] == '\n' || buffer[i] == '\r'){
website_HTML+=buffer[i];
i += 1;
}
}
closesocket(Socket);
WSACleanup();
// Display HTML source
cout<<website_HTML;
// pause
cout<<"\n\nPress ANY key to close.\n\n";
cin.ignore(); cin.get();
return 0;
}
這是一個更好的實現:
#include <windows.h>
#include <string>
#include <stdio.h>
using std::string;
#pragma comment(lib,"ws2_32.lib")
HINSTANCE hInst;
WSADATA wsaData;
void mParseUrl(char *mUrl, string &serverName, string &filepath, string &filename);
SOCKET connectToServer(char *szServerName, WORD portNum);
int getHeaderLength(char *content);
char *readUrl2(char *szUrl, long &bytesReturnedOut, char **headerOut);
int main()
{
const int bufLen = 1024;
char *szUrl = "http://stackoverflow.com";
long fileSize;
char *memBuffer, *headerBuffer;
FILE *fp;
memBuffer = headerBuffer = NULL;
if ( WSAStartup(0x101, &wsaData) != 0)
return -1;
memBuffer = readUrl2(szUrl, fileSize, &headerBuffer);
printf("returned from readUrl\n");
printf("data returned:\n%s", memBuffer);
if (fileSize != 0)
{
printf("Got some data\n");
fp = fopen("downloaded.file", "wb");
fwrite(memBuffer, 1, fileSize, fp);
fclose(fp);
delete(memBuffer);
delete(headerBuffer);
}
WSACleanup();
return 0;
}
void mParseUrl(char *mUrl, string &serverName, string &filepath, string &filename)
{
string::size_type n;
string url = mUrl;
if (url.substr(0,7) == "http://")
url.erase(0,7);
if (url.substr(0,8) == "https://")
url.erase(0,8);
n = url.find('/');
if (n != string::npos)
{
serverName = url.substr(0,n);
filepath = url.substr(n);
n = filepath.rfind('/');
filename = filepath.substr(n+1);
}
else
{
serverName = url;
filepath = "/";
filename = "";
}
}
SOCKET connectToServer(char *szServerName, WORD portNum)
{
struct hostent *hp;
unsigned int addr;
struct sockaddr_in server;
SOCKET conn;
conn = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (conn == INVALID_SOCKET)
return NULL;
if(inet_addr(szServerName)==INADDR_NONE)
{
hp=gethostbyname(szServerName);
}
else
{
addr=inet_addr(szServerName);
hp=gethostbyaddr((char*)&addr,sizeof(addr),AF_INET);
}
if(hp==NULL)
{
closesocket(conn);
return NULL;
}
server.sin_addr.s_addr=*((unsigned long*)hp->h_addr);
server.sin_family=AF_INET;
server.sin_port=htons(portNum);
if(connect(conn,(struct sockaddr*)&server,sizeof(server)))
{
closesocket(conn);
return NULL;
}
return conn;
}
int getHeaderLength(char *content)
{
const char *srchStr1 = "\r\n\r\n", *srchStr2 = "\n\r\n\r";
char *findPos;
int ofset = -1;
findPos = strstr(content, srchStr1);
if (findPos != NULL)
{
ofset = findPos - content;
ofset += strlen(srchStr1);
}
else
{
findPos = strstr(content, srchStr2);
if (findPos != NULL)
{
ofset = findPos - content;
ofset += strlen(srchStr2);
}
}
return ofset;
}
char *readUrl2(char *szUrl, long &bytesReturnedOut, char **headerOut)
{
const int bufSize = 512;
char readBuffer[bufSize], sendBuffer[bufSize], tmpBuffer[bufSize];
char *tmpResult=NULL, *result;
SOCKET conn;
string server, filepath, filename;
long totalBytesRead, thisReadSize, headerLen;
mParseUrl(szUrl, server, filepath, filename);
///////////// step 1, connect //////////////////////
conn = connectToServer((char*)server.c_str(), 80);
///////////// step 2, send GET request /////////////
sprintf(tmpBuffer, "GET %s HTTP/1.0", filepath.c_str());
strcpy(sendBuffer, tmpBuffer);
strcat(sendBuffer, "\r\n");
sprintf(tmpBuffer, "Host: %s", server.c_str());
strcat(sendBuffer, tmpBuffer);
strcat(sendBuffer, "\r\n");
strcat(sendBuffer, "\r\n");
send(conn, sendBuffer, strlen(sendBuffer), 0);
// SetWindowText(edit3Hwnd, sendBuffer);
printf("Buffer being sent:\n%s", sendBuffer);
///////////// step 3 - get received bytes ////////////////
// Receive until the peer closes the connection
totalBytesRead = 0;
while(1)
{
memset(readBuffer, 0, bufSize);
thisReadSize = recv (conn, readBuffer, bufSize, 0);
if ( thisReadSize <= 0 )
break;
tmpResult = (char*)realloc(tmpResult, thisReadSize+totalBytesRead);
memcpy(tmpResult+totalBytesRead, readBuffer, thisReadSize);
totalBytesRead += thisReadSize;
}
headerLen = getHeaderLength(tmpResult);
long contenLen = totalBytesRead-headerLen;
result = new char[contenLen+1];
memcpy(result, tmpResult+headerLen, contenLen);
result[contenLen] = 0x0;
char *myTmp;
myTmp = new char[headerLen+1];
strncpy(myTmp, tmpResult, headerLen);
myTmp[headerLen] = NULL;
delete(tmpResult);
*headerOut = myTmp;
bytesReturnedOut = contenLen;
closesocket(conn);
return(result);
}
2020 年更新:我有一個新的答案來取代這個,現在已經 8 歲了,一個: https ://stackoverflow.com/a/61177330/278976
在 Linux 上,我嘗試了 cpp-netlib、libcurl、curlpp、urdl、boost::asio 並考慮了 Qt(但根據許可證拒絕了它)。 所有這些要么不完整,要么不完整,界面草率,文檔差,未維護或不支持 https。
然后,在https://stackoverflow.com/a/1012577/278976的建議下,我嘗試了 POCO。 哇,我真希望我幾年前就看到了。 下面是一個使用 POCO 發出 HTTP GET 請求的示例:
https://stackoverflow.com/a/26026828/2817595
POCO 是免費的、開源的(增強許可證)。 不,我與公司沒有任何關系; 我真的很喜歡他們的界面。 干得好家伙(和女孩)。
https://pocoproject.org/download.html
希望這對某人有所幫助……我花了三天時間嘗試所有這些庫。
正在開發一種更新的、不太成熟的 curl 包裝器,稱為C++ Requests 。 這是一個簡單的 GET 請求:
#include <iostream>
#include <cpr.h>
int main(int argc, char** argv) {
auto response = cpr::Get(cpr::Url{"http://httpbin.org/get"});
std::cout << response.text << std::endl;
}
它支持多種 HTTP 動詞和 curl 選項。 這里有更多使用文檔。
免責聲明:我是這個庫的維護者。
2020 年 4 月的更新答案:
最近,我使用cpp-httplib (作為客戶端和服務器)取得了很大的成功。 它很成熟,其近似的單線程 RPS 約為 6k。
在更前沿,有一個非常有前途的框架cpv-framework ,它可以在兩個內核上獲得大約 180k RPS(並且可以很好地隨內核數量擴展,因為它基於seastar框架,它為最快的數據庫提供動力星球, scylladb )。
但是cpv-framework還比較不成熟; 因此,對於大多數用途,我強烈推薦 cpp-httplib。
此建議取代了我之前的答案(8 年前)。
這是我對 cURL 的最小包裝,它能夠將網頁作為字符串獲取。 例如,這對於單元測試很有用。 它基本上是 C 代碼的 RAII 包裝器。
在你的機器上安裝“libcurl” yum install libcurl libcurl-devel
或等效的。
使用示例:
CURLplusplus client;
string x = client.Get("http://google.com");
string y = client.Get("http://yahoo.com");
類實現:
#include <curl/curl.h>
class CURLplusplus
{
private:
CURL* curl;
stringstream ss;
long http_code;
public:
CURLplusplus()
: curl(curl_easy_init())
, http_code(0)
{
}
~CURLplusplus()
{
if (curl) curl_easy_cleanup(curl);
}
std::string Get(const std::string& url)
{
CURLcode res;
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, this);
ss.str("");
http_code = 0;
res = curl_easy_perform(curl);
if (res != CURLE_OK)
{
throw std::runtime_error(curl_easy_strerror(res));
}
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
return ss.str();
}
long GetHttpCode()
{
return http_code;
}
private:
static size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp)
{
return static_cast<CURLplusplus*>(userp)->Write(buffer,size,nmemb);
}
size_t Write(void *buffer, size_t size, size_t nmemb)
{
ss.write((const char*)buffer,size*nmemb);
return size*nmemb;
}
};
您可能需要檢查C++ REST SDK (代號“Casablanca”)。 http://msdn.microsoft.com/en-us/library/jj950081.aspx
使用 C++ REST SDK,您可以更輕松地從 C++ 應用程序連接到 HTTP 服務器。
使用示例:
#include <iostream>
#include <cpprest/http_client.h>
using namespace web::http; // Common HTTP functionality
using namespace web::http::client; // HTTP client features
int main(int argc, char** argv) {
http_client client("http://httpbin.org/");
http_response response;
// ordinary `get` request
response = client.request(methods::GET, "/get").get();
std::cout << response.extract_string().get() << "\n";
// working with json
response = client.request(methods::GET, "/get").get();
std::cout << "url: " << response.extract_json().get()[U("url")] << "\n";
}
C++ REST SDK 是一個 Microsoft 項目,用於使用現代異步 C++ API 設計以本機代碼進行基於雲的客戶端-服務器通信。
有了這個答案,我參考了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;
}
參考:
C++ 沒有提供任何直接執行此操作的方法。 這完全取決於您擁有的平台和庫。
在最壞的情況下,您可以使用 boost::asio 庫建立 TCP 連接,發送 HTTP 標頭 (RFC 2616),並直接解析響應。 查看您的應用程序需求,這很簡單。
以下是一些無需使用任何第三方庫即可工作的代碼:首先定義您的網關、用戶、密碼和您需要發送到此特定服務器的任何其他參數。
#define USERNAME "user"
#define PASSWORD "your password"
#define GATEWAY "your gateway"
這是代碼本身:
HINTERNET hOpenHandle, hResourceHandle, hConnectHandle;
const TCHAR* szHeaders = _T("Content-Type:application/json; charset=utf-8\r\n");
hOpenHandle = InternetOpen(_T("HTTPS"), INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
if (hOpenHandle == NULL)
{
return false;
}
hConnectHandle = InternetConnect(hOpenHandle,
GATEWAY,
INTERNET_DEFAULT_HTTPS_PORT,
NULL, NULL, INTERNET_SERVICE_HTTP,
0, 1);
if (hConnectHandle == NULL)
{
InternetCloseHandle(hOpenHandle);
return false;
}
hResourceHandle = HttpOpenRequest(hConnectHandle,
_T("POST"),
GATEWAY,
NULL, NULL, NULL, INTERNET_FLAG_SECURE | INTERNET_FLAG_KEEP_CONNECTION,
1);
if (hResourceHandle == NULL)
{
InternetCloseHandle(hOpenHandle);
InternetCloseHandle(hConnectHandle);
return false;
}
InternetSetOption(hResourceHandle, INTERNET_OPTION_USERNAME, (LPVOID)USERNAME, _tcslen(USERNAME));
InternetSetOption(hResourceHandle, INTERNET_OPTION_PASSWORD, (LPVOID)PASSWORD, _tcslen(PASSWORD));
std::string buf;
if (HttpSendRequest(hResourceHandle, szHeaders, 0, NULL, 0))
{
while (true)
{
std::string part;
DWORD size;
if (!InternetQueryDataAvailable(hResourceHandle, &size, 0, 0))break;
if (size == 0)break;
part.resize(size);
if (!InternetReadFile(hResourceHandle, &part[0], part.size(), &size))break;
if (size == 0)break;
part.resize(size);
buf.append(part);
}
}
if (!buf.empty())
{
// Get data back
}
InternetCloseHandle(hResourceHandle);
InternetCloseHandle(hConnectHandle);
InternetCloseHandle(hOpenHandle);
這應該適用於 Win32 API 環境。
這是一個例子。
請注意,這不需要 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 Monikers 和異步可插入協議參考
HTTP協議很簡單,所以寫一個HTTP客戶端也很簡單。 這是一個
https://github.com/pedro-vicente/lib_netsockets
它使用 HTTP GET 從 Web 服務器檢索文件,服務器和文件都是命令行參數。 遠程文件保存到本地副本。
免責聲明:我是作者
檢查 http.cc https://github.com/pedro-vicente/lib_netsockets/blob/master/src/http.cc
int http_client_t::get(const char *path_remote_file)
{
char buf_request[1024];
//construct request message using class input parameters
sprintf(buf_request, "GET %s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n", path_remote_file, m_server_ip.c_str());
//send request, using built in tcp_client_t socket
if (this->write_all(buf_request, (int)strlen(buf_request)) < 0)
{
return -1;
}
編輯:編輯的網址
C 和 C++ 沒有用於 HTTP 甚至用於套接字連接的標准庫。 多年來,已經開發了一些可移植的庫。 正如其他人所說,使用最廣泛的是libcurl 。
這是 libcurl 的替代品列表(來自 libcurl 的網站)。
此外,對於 Linux, 這是一個簡單的 HTTP 客戶端。 您可以實現自己的簡單 HTTP GET 客戶端,但如果涉及身份驗證或重定向,或者您需要在代理后面工作,這將不起作用。 對於這些情況,您需要一個成熟的庫,例如 libcurl。
對於帶有 libcurl 的源代碼,這是最接近您想要的(Libcurl 有很多示例)。 看主函數。 成功連接后,html 內容將被復制到緩沖區。 只需將 parseHtml 替換為您自己的函數即可。
這是一些(相對)簡單的 C++11 代碼,它使用 libCURL 將 URL 的內容下載到std::vector<char>
:
# pragma once
#include <string>
#include <vector>
std::vector<char> download(std::string url, long* responseCode = nullptr);
#include "http_download.hh"
#include <curl/curl.h>
#include <sstream>
#include <stdexcept>
using namespace std;
size_t callback(void* contents, size_t size, size_t nmemb, void* user)
{
auto chunk = reinterpret_cast<char*>(contents);
auto buffer = reinterpret_cast<vector<char>*>(user);
size_t priorSize = buffer->size();
size_t sizeIncrease = size * nmemb;
buffer->resize(priorSize + sizeIncrease);
std::copy(chunk, chunk + sizeIncrease, buffer->data() + priorSize);
return sizeIncrease;
}
vector<char> download(string url, long* responseCode)
{
vector<char> data;
curl_global_init(CURL_GLOBAL_ALL);
CURL* handle = curl_easy_init();
curl_easy_setopt(handle, CURLOPT_URL, url.c_str());
curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, callback);
curl_easy_setopt(handle, CURLOPT_WRITEDATA, &data);
curl_easy_setopt(handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
CURLcode result = curl_easy_perform(handle);
if (responseCode != nullptr)
curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, responseCode);
curl_easy_cleanup(handle);
curl_global_cleanup();
if (result != CURLE_OK)
{
stringstream err;
err << "Error downloading from URL \"" << url << "\": " << curl_easy_strerror(result);
throw runtime_error(err.str());
}
return data;
}
您可以使用EmbeddedRest庫。 它是輕量級的僅頭文件庫。 因此很容易將它包含到您的項目中,並且不需要編譯,因為其中沒有.cpp
文件。
從 repo 的readme.md
請求示例:
#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;
}
如果您正在尋找一個支持多個平台(Linux、Windows 和 Mac)的 C++ HTTP 客戶端庫來使用 Restful Web 服務。 您可以有以下選項。
一般來說,我會推薦一些跨平台的東西,比如 cURL、POCO 或 Qt。 但是,這是一個 Windows 示例!:
#include <atlbase.h>
#include <msxml6.h>
#include <comutil.h> // _bstr_t
HRESULT hr;
CComPtr<IXMLHTTPRequest> request;
hr = request.CoCreateInstance(CLSID_XMLHTTP60);
hr = request->open(
_bstr_t("GET"),
_bstr_t("https://www.google.com/images/srpr/logo11w.png"),
_variant_t(VARIANT_FALSE),
_variant_t(),
_variant_t());
hr = request->send(_variant_t());
// get status - 200 if succuss
long status;
hr = request->get_status(&status);
// load image data (if url points to an image)
VARIANT responseVariant;
hr = request->get_responseStream(&responseVariant);
IStream* stream = (IStream*)responseVariant.punkVal;
CImage *image = new CImage();
image->Load(stream);
stream->Release();
雖然有點晚了。 您可能更喜歡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 歲了。 然而 。 提供的答案都沒有給出一個“簡單”的例子,不需要構建一些外部庫
以下是我能想到的最簡單的解決方案,用於檢索和打印網頁內容。
#include <iostream>
#pragma comment(lib, "wininet.lib")
#include <WinSock2.h>
#include <wininet.h>
int main()
{
std::string RESULT{};
const int size = 4096;
char buf[size];
DWORD length;
HINTERNET internet = InternetOpenA("Mozilla/5.0", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, NULL);
if (!internet)
ExitProcess(EXIT_FAILURE);
HINTERNET response = InternetOpenUrlA(internet, "http://www.google.com", NULL, NULL, NULL, NULL);
if (!response) {
InternetCloseHandle(internet);
ExitProcess(EXIT_FAILURE);
}
InternetReadFile(response, buf, size, &length);
InternetCloseHandle(response);
InternetCloseHandle(internet);
std::cout << buf << std::endl;
return 0;
}
您可以使用 ACE 來執行此操作:
#include "ace/SOCK_Connector.h"
int main(int argc, ACE_TCHAR* argv[])
{
//HTTP Request Header
char* szRequest = "GET /video/nice.mp4 HTTP/1.1\r\nHost: example.com\r\n\r\n";
int ilen = strlen(szRequest);
//our buffer
char output[16*1024];
ACE_INET_Addr server (80, "example.com");
ACE_SOCK_Stream peer;
ACE_SOCK_Connector connector;
int ires = connector.connect(peer, server);
int sum = 0;
peer.send(szRequest, ilen);
while (true)
{
ACE_Time_Value timeout = ACE_Time_Value(15);
int rc = peer.recv_n(output, 16*1024, &timeout);
if (rc == -1)
{
break;
}
sum += rc;
}
peer.close();
printf("Bytes transffered: %d",sum);
return 0;
}
MS 的 CppRest SDK 是我剛剛發現的,大約 1/2 小時后,我的第一個簡單的 Web 服務調用開始工作。 與這里提到的其他人相比,即使經過數小時的查看,我什至無法安裝任何東西,我會說它非常令人印象深刻
https://github.com/microsoft/cpprestsdk
向下滾動並單擊文檔,然后單擊入門教程,您將立即運行一個簡單的應用程序。
作為記錄,cesanta 的貓鼬庫似乎也支持這一點: https ://github.com/cesanta/mongoose/blob/6.17/examples/http_client/http_client.c
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.