C ++ ile kolayca bir HTTP isteği yapmanın bir yolu var mı? Özellikle, bir sayfanın (API) içeriğini indirmek ve 1 veya 0 içerip içermediğini görmek için içeriği kontrol etmek istiyorum. İçeriği bir dizeye indirmek de mümkün mü?
C ++ ile kolayca bir HTTP isteği yapmanın bir yolu var mı? Özellikle, bir sayfanın (API) içeriğini indirmek ve 1 veya 0 içerip içermediğini görmek için içeriği kontrol etmek istiyorum. İçeriği bir dizeye indirmek de mümkün mü?
Yanıtlar:
Ben de aynı problemi yaşadım. libcurl gerçekten tamamlandı. Bir C ++ kitaplığı istediğinde ilginizi çekebilecek bir C ++ sarıcı curlpp var. neon , WebDAV'ı da destekleyen bir başka ilginç C kütüphanesidir .
C ++ kullanıyorsanız curlpp doğal görünüyor. Kaynak dağıtımında birçok örnek verilmiştir. Bir URL'nin içeriğini almak için böyle bir şey yaparsınız (örneklerden çıkarılır):
// 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://www.wikipedia.org"));
string asAskedInQuestion = os.str();
Curlpp kaynak dağıtımındakiexamples
dizine bakın, çok daha karmaşık vakaların yanı sıra curlpp kullanarak basit bir tam minimal bir tane var.
2 sentim ...
os << myRequest.perform();
ile myRequest.setOpt( new curlpp::options::WriteStream( &os ) ); myRequest.perform();
verdi sonuçların. Kullanmamaya dikkat edin http://example.com
, bu boş bir sayfa döndürür. Daha iyi kullanım örn http://www.wikipedia.org
.
Windows kodu:
#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;
}
İşte çok daha iyi bir uygulama:
#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);
}
GET / HTTP/1.1.1/... etc
) Yaptığınızı koydunuz ? Gönderdiğimi nasıl biçimlendireceğimi nasıl öğrenebilirim?
Güncelleme 2020: Şimdi 8 yaşında olanın yerine yeni bir cevabım var: https://stackoverflow.com/a/61177330/278976
Linux'ta cpp-netlib, libcurl, curlpp, urdl, boost :: asio'yu denedim ve Qt olarak düşündüm (ancak lisansa göre geri çevirdim). Bunların hepsi ya bu kullanım için eksikti, özensiz arayüzlere sahipti, zayıf dokümantasyona sahipti, bakımsızdı ya da https'yi desteklemedi.
Sonra, https://stackoverflow.com/a/1012577/278976 önerisinde POCO'yu denedim. Vay, keşke bu yıllar önce görseydim. İşte POCO ile HTTP GET isteği yapma örneği:
https://stackoverflow.com/a/26026828/2817595
POCO ücretsiz, açık kaynaklıdır (lisans yükseltme). Ve hayır, şirketle hiçbir ilişkim yok; Arayüzlerini gerçekten çok seviyorum. Harika iş adamları (ve kızlar).
https://pocoproject.org/download.html
Umarım bu birine yardımcı olur ... tüm bu kütüphaneleri denemek üç günümü aldı.
C ++ İstekleri olarak adlandırılan daha yeni, daha az olgun bir kıvırma sarıcısı geliştirilmektedir . İşte basit bir GET isteği:
#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;
}
Çok çeşitli HTTP fiilleri ve kıvırma seçeneklerini destekler. Burada daha fazla kullanım belgesi var .
Feragatname: Bu kütüphanenin koruyucusuyum .
İşte bir web sayfasını dize olarak alabilmek için cURL etrafındaki minimal paketleyicim. Bu, örneğin birim testi için kullanışlıdır. Temelde C kodu etrafında bir RAII sarıcıdır.
Makinenize yum install libcurl libcurl-devel
veya eşdeğerinize "libcurl" yükleyin .
Kullanım örneği:
CURLplusplus client;
string x = client.Get("http://google.com");
string y = client.Get("http://yahoo.com");
Sınıf uygulaması:
#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;
}
};
libCURL sizin için oldukça iyi bir seçenek. Ne yapmanız gerektiğine bağlı olarak, öğretici özellikle kolay kullanım için ne istediğinizi söylemelidir. Ancak, temel olarak, bunu yalnızca bir sayfanın kaynağını görmek için yapabilirsiniz:
CURL* c;
c = curl_easy_init();
curl_easy_setopt( c, CURL_URL, "www.google.com" );
curl_easy_perform( c );
curl_easy_cleanup( c );
Bunun sonucun yazdırılmasına neden olacağına inanıyorum. Onun yerine ele almak istiyorsanız - ki, sanırım, sen - CURL_WRITEFUNCTION ayarlamanız gerekir. Bunların tümü, yukarıda bağlantılı olan kıvırma eğitiminde ele alınmıştır.
Bir C ++ çözümü istediğiniz gibi, Qt kullanabilirsiniz . Kullanabileceğiniz bir QHttp sınıfı vardır.
Dokümanları kontrol edebilirsiniz :
http->setHost("qt.nokia.com");
http->get(QUrl::toPercentEncoding("/index.html"));
Qt ayrıca ortak bir C ++ uygulamasında kullanabileceğiniz çok daha fazlasına sahiptir.
QNetworkAccessManager
Qt 4.4'ten beri belgelenmiştir; Ve Qt 4.8'de şöyle diyor: QHttp - This class is obsolete. It is provided to keep old source code working. We strongly advise against using it in new code.
Yani, kullanımdan kaldırılmış uyarıları görmezden gelirseniz, hala kullanılabilir.
C ++ REST SDK'sını (kod adı "Casablanca") kontrol etmek isteyebilirsiniz . http://msdn.microsoft.com/en-us/library/jj950081.aspx
C ++ REST SDK ile C ++ uygulamanızdan HTTP sunucularına daha kolay bağlanabilirsiniz.
Kullanım örneği:
#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, modern bir eşzamansız C ++ API tasarımı kullanarak yerel kodda bulut tabanlı istemci-sunucu iletişimi için bir Microsoft projesidir.
Bu cevapla Software_Developer'ın cevabına atıfta bulunuyorum . Kodu yeniden oluşturarak bazı parçaların kullanımdan kaldırıldığını ( gethostbyname()
) veya hata işlemeyi sağlamadığını gördüm (soket oluşturma, bir şey gönderme) .
Aşağıdaki Windows kodu , Visual Studio 2013 ve Windows 8.1 64-bit ve Windows 7 64-bit ile test edilmiştir. Www.google.com Web Sunucusu ile bir IPv4 TCP Bağlantısını hedefleyecektir.
#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;
}
Referanslar:
C ++ doğrudan yapmak için herhangi bir yol sağlamaz. Bu tamamen sahip olduğunuz platformlara ve kütüphanelere bağlıdır.
En kötü durumda, bir TCP bağlantısı kurmak, HTTP üstbilgilerini (RFC 2616) göndermek ve yanıtları doğrudan ayrıştırmak için boost :: asio kütüphanesini kullanabilirsiniz. Uygulama ihtiyaçlarınıza bakarak, bunu yapmak için yeterince basit.
İşte herhangi bir 3. taraf kitaplığı kullanmaya gerek kalmadan çalışacak bazı kodlar: İlk olarak ağ geçidinizi, kullanıcınızı, şifrenizi ve bu sunucuya göndermeniz gereken diğer parametreleri tanımlayın.
#define USERNAME "user"
#define PASSWORD "your password"
#define GATEWAY "your gateway"
İşte kodun kendisi:
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);
Bu bir Win32 API ortamında çalışmalıdır.
İşte bir örnek .
InternetConnect
tam URL verildiğinde null değerini döndürür, ancak yalnızca alan adı belirtildiğinde null olmayan değeri döndürür. Peki, indirmek istediğim sayfayı almak için tam URL'yi ne zaman / nerede kullanırım?
Nisan 2020 için cevap güncellendi:
Son zamanlarda cpp-httplib (hem istemci hem de sunucu olarak) ile çok başarılı oldum . Olgun ve yaklaşık tek dişli RPS yaklaşık 6k.
Kanama kenar daha günü, gerçekten umut verici çerçeve var gbm-çerçeve iki çekirdek etrafında 180k RPS alabilirsiniz (ve temel aldığı için çekirdek sayısı ile ölçeklendirilebileceği, seastar çerçevesinde, yetki hızlı DBs üzerinde gezegen, scylladb ).
Bununla birlikte, cpv-framework hala nispeten olgunlaşmamış durumda; yani, çoğu kullanım için, cpp-httplib tavsiye ederim.
Bu öneri önceki cevabımın yerini alıyor (8 yıl önce).
C ve C ++ 'nın HTTP veya soket bağlantıları için standart bir kütüphanesi yoktur. Yıllar içinde bazı taşınabilir kütüphaneler geliştirilmiştir. Diğerlerinin söylediği gibi en yaygın kullanılan libcurl .
İşte bir liste libcurl (libcurl web sitesinden gelen) alternatiflerinin .
Ayrıca, Linux için bu basit bir HTTP istemcisidir. Kendi basit HTTP GET istemcinizi uygulayabilirsiniz, ancak ilgili kimlik doğrulama veya yönlendirmeler varsa veya bir proxy'nin arkasında çalışmanız gerekiyorsa bu çalışmaz. Bu durumlar için libcurl gibi tam bir kütüphaneye ihtiyacınız var.
Libcurl içeren kaynak kodu için bu , istediğiniz şeye en yakın olanıdır (Libcurl'un birçok örneği vardır ). Ana işleve bakın. Html içeriği başarılı bir bağlantıdan sonra ara belleğe kopyalanır. Sadece parseHtml dosyasını kendi işlevinizle değiştirin.
EmbeddedRest kitaplığını kullanabilirsiniz . Hafif başlık sadece bir kütüphanedir. Bu yüzden projenize dahil etmek kolaydır ve derleme gerektirmez, çünkü hayır.cpp
içinde dosya .
Repo'dan örnek isteyin 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;
}
netdb.h
ben biraz yardım evet istiyorum böylece vb
HTTP protokolü çok basit, bu nedenle bir HTTP istemcisi yazmak çok basit. İşte burada
https://github.com/pedro-vicente/lib_netsockets
Bir web sunucusundan bir dosya almak için HTTP GET kullanır, hem sunucu hem de dosya komut satırı parametreleridir. Uzak dosya yerel bir kopyaya kaydedilir.
Feragatname: Ben yazarım
EDIT: düzenlenmiş URL
Bunun libcurl, Windows.h veya WinSock gerektirmediğine dikkat edin! Hiçbir derleme kütüphaneleri, hiçbir proje yapılandırması, vb. Windows 10 üzerinde Visual Studio 2017 c ++ ile çalışan bu kodu var:
#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();
Basit bir API erişim komut dosyası istediğim için bunu nasıl yapacağımı anladım, libcurl gibi kütüphaneler bana her türlü soruna neden oluyordu (talimatları takip ettiğimde bile ...) ve WinSock çok düşük seviyeli ve karmaşık .
Tüm IStream okuma kodu (özellikle while koşulu - düzeltmek / geliştirmek için çekinmeyin) hakkında emin değilim , ama hey, o sorunsuz çalışır ! (Bir engelleme (eşzamanlı) çağrısı kullandığım için , bu iyi, bytesRead
akışın ( ISequentialStream ?) Okunması bitene kadar her zaman> 0U olacağı mantıklı .
Ayrıca bkz: URL Takma Adları ve Eşzamansız Takılabilir Protokol Başvurusu
Bir URL'nin içeriğini bir URL'ye indirmek için libCURL kullanan bazı (nispeten) basit C ++ 11 kodu 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 move(data);
}
Genellikle cURL, POCO veya Qt gibi platformlar arası bir şey öneriyorum. Ancak, işte bir Windows örneği !:
#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();
Huzurlu web hizmetlerini tüketmek için birden fazla platformda (Linux, Windows ve Mac) desteklenen bir C ++ HTTP sunucusu arşivi arıyorsanız. Aşağıdaki seçeneklere sahip olabilirsiniz.
Biraz geç olmasına rağmen. Https://github.com/Taymindis/backcurl tercih edebilirsiniz .
Mobil c ++ geliştirmede http araması yapmanızı sağlar. Mobil oyun geliştirme için uygun
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
ACE'yi kullanarak şunları yapabilirsiniz:
#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;
}