Sign in to follow this  

[web] C++ HTTP Requests

This topic is 4365 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I saw a thread on it about a week or two ago but sadly the search and my attempt at a manual search resulted in a miserable failure. Does anyone know how to make HTTP requests from C++ (not .NET)? I'm looking to setup a PHP script that will take a highscore along with some type of key to validate it. The application will then call the script and upload the highscores. Or if there is any other solution available, that would be great. Maybe even running remote MySQL queries directly from the application....

Share this post


Link to post
Share on other sites
I use libcurl http://curl.haxx.se/ to perform http queries. It's easy to set up a multiplayer game to request a php script that returns a list of servers for example, and easy to run the php script with variables in the url to interact more with the database.

Share this post


Link to post
Share on other sites
Quote:
Original post by Rob Loach
Or if there is any other solution available, that would be great. Maybe even running remote MySQL queries directly from the application....


No that would be less than ideal.

This is because the user would be able to detect the MySQL login / password and put in their own data, which would be bad.

Using a PHP (or even a CGI program written in C++, maybe, so it can reuse code from the app itself) script to update high scores, list servers etc, is definitely the way to go.

It's much easier to code this sort of high-score updater or server-list manager in PHP than it would be in C++ (well, if you know PHP anyway).

A server-list manager would need to be able to query servers though to check that they were online

Mark

Share this post


Link to post
Share on other sites
I suggest going the libcurl route. I've attached a really simple HTTP GET class. It should be easily modifiable to support HTTP POST or SSL, if that's what you need:

I decided to go the stateful route (only allowing the object to handle one download at a time) for 2 reasons: It allowed easy re-use of the CURL handle (which allows for pipelined transactions), and it allowed me to re-use buffers (so the user doesn't have to allocate their own entire buffer ahead of time, they just have to get a pointer). This has the downside of keeping a buffer around that's as large as the largest file you ever downloaded, but for my application, that doesn't matter. In my usage, almost all downloads will be about the same size, pipelineing is important, and the downloads will only be about ~1meg.

If all you're doing is reporting scores, then the buffer size should stay small, and it won't matter.

Obviously, the content/contentLength/contentType will be overwritten on each call to downloadFile().

HTTPDownloader.h:

#include <string>
#include <curl/curl.h>

#ifndef HTTP_DOWNLOADER_GUARD
#define HTTP_DOWNLOADER_GUARD

class HTTPDownloader {
public:
HTTPDownloader();
~HTTPDownloader();

bool downloadFile(const std::string url);
std::string contentType() const;
unsigned int contentLength() const;
char* content() const;

private:

static size_t httpFetch(void* ptr, size_t size, size_t nmemb, void* stream);

CURL* curlHandle;
char* data;
unsigned int length;
unsigned int allocatedLength;
std::string type;
};

#endif /* HTTP_DOWNLOADER_GUARD */




HTTPDownloader.cpp

#include "HTTPDownloader.h"
#include <iostream>
#include <cassert>

using namespace std;

const int kInitialBufferSize = 1024*1024;

HTTPDownloader::HTTPDownloader():
curlHandle(curl_easy_init()), data(NULL), length(0), allocatedLength(0)
{}

HTTPDownloader::~HTTPDownloader() {
curl_easy_cleanup(curlHandle);
if (data) {
free(data);
data = NULL;
allocatedLength = 0;
length = 0;
}
}

bool HTTPDownloader::downloadFile(const std::string url) {
length = 0;

// set up transfer
CURLcode curlErr = curl_easy_setopt(curlHandle, CURLOPT_URL, url.c_str());
if (curlErr != CURLE_OK) {
cerr << "got curl error on setopt url " << curlErr << endl;
return false;
}
curlErr = curl_easy_setopt(curlHandle, CURLOPT_WRITEFUNCTION, httpFetch);
if (curlErr != CURLE_OK) {
cerr << "got curl error on setopt func " << curlErr << endl;
return false;
}
curlErr = curl_easy_setopt(curlHandle, CURLOPT_WRITEDATA, this);
if (curlErr != CURLE_OK) {
cerr << "got curl error on setopt url " << curlErr << endl;
return false;
}

// perform transfer
curlErr = curl_easy_perform(curlHandle);
if (curlErr != CURLE_OK) {
cerr << "got curl error on perform " << curlErr << endl;
return false;
}

char* contentType = NULL;
curlErr = curl_easy_getinfo(curlHandle, CURLINFO_CONTENT_TYPE, &contentType);
if (curlErr != CURLE_OK) {
cerr << "got curl error on getopt for CONTENT_TYPE " << curlErr << endl;
return false;
}
type = string(contentType);

return true;
}

std::string HTTPDownloader::contentType() const {
return type;
}

unsigned int HTTPDownloader::contentLength() const {
return length;
}

char* HTTPDownloader::content() const {
return data;
}

size_t HTTPDownloader::httpFetch(void* ptr, size_t size, size_t nmemb, void* stream) {
HTTPDownloader* handle = (HTTPDownloader*)stream;
size_t newDataSize = size*nmemb;

if (handle->data == NULL) {
assert(handle->allocatedLength == 0);
handle->data = (char*)malloc(kInitialBufferSize);
handle->allocatedLength = kInitialBufferSize;
handle->length = 0;
}

while (handle->length+newDataSize+1 > handle->allocatedLength) {
assert(handle->allocatedLength > 0);
handle->data = (char*)realloc(handle->data, handle->allocatedLength*2);
handle->allocatedLength *= 2;
}

memcpy(handle->data + handle->length, ptr, newDataSize);
handle->length += newDataSize;
return newDataSize;
}


Share this post


Link to post
Share on other sites
Why not simply use sockets and send out the HTTP requests directly by yourself? As long as you don't anything too fancy, it won't be really hard. And there is a lot of resource available on the HTTP protocol on internet.

Share this post


Link to post
Share on other sites
Hi,

I thought this might be a good thread to ask for help in...

I've been trying to get libcurl to work with the curlpp wrapper. I have managed to compile libcurl into a .lib/.dll but cannot do the same with curlpp. Well... I have compiled a dll but my project does not accept it.

I have instead #included the required files in my project but am still getting errors.

E.g.

Linking...
Creating library Debug/test_project.lib and object Debug/test_project.exp
urlReader.obj : error LNK2019: unresolved external symbol "public: virtual void __thiscall cURLpp::Easy::setOpt(class cURLpp::OptionBase const &)" (?setOpt@Easy@cURLpp@@UAEXABVOptionBase@2@@Z) referenced in function "private: int __thiscall urlReader::saveData(void)" (?saveData@urlReader@@AAEHXZ)
urlReader.obj : error LNK2019: unresolved external symbol "void __cdecl cURLpp::initialize(long)" (?initialize@cURLpp@@YAXJ@Z) referenced in function "private: int __thiscall urlReader::saveData(void)" (?saveData@urlReader@@AAEHXZ)
urlReader.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall cURLpp::OptionList::getOpt(class cURLpp::OptionBase *)" (?getOpt@OptionList@cURLpp@@UAEXPAVOptionBase@2@@Z)
urlReader.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall cURLpp::Easy::setOpt(class cURLpp::OptionBase *)" (?setOpt@Easy@cURLpp@@UAEXPAVOptionBase@2@@Z)
urlReader.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall cURLpp::Easy::setOpt(class cURLpp::OptionList const &)" (?setOpt@Easy@cURLpp@@UAEXABVOptionList@2@@Z)
urlReader.obj : error LNK2019: unresolved external symbol "public: virtual __thiscall cURLpp::OptionList::~OptionList(void)" (??1OptionList@cURLpp@@UAE@XZ) referenced in function __unwindfunclet$??0Easy@cURLpp@@QAE@XZ$0
urlReader.obj : error LNK2019: unresolved external symbol "public: __thiscall cURLpp::CurlHandle::CurlHandle(void)" (??0CurlHandle@cURLpp@@QAE@XZ) referenced in function "public: __thiscall cURLpp::Easy::Easy(void)" (??0Easy@cURLpp@@QAE@XZ)
urlReader.obj : error LNK2019: unresolved external symbol "public: __thiscall cURLpp::OptionList::OptionList(void)" (??0OptionList@cURLpp@@QAE@XZ) referenced in function "public: __thiscall cURLpp::Easy::Easy(void)" (??0Easy@cURLpp@@QAE@XZ)
urlReader.obj : error LNK2019: unresolved external symbol "public: virtual __thiscall cURLpp::CurlHandle::~CurlHandle(void)" (??1CurlHandle@cURLpp@@UAE@XZ) referenced in function "public: virtual __thiscall cURLpp::Easy::~Easy(void)" (??1Easy@cURLpp@@UAE@XZ)
urlReader.obj : error LNK2001: unresolved external symbol "public: virtual bool __thiscall cURLpp::OptionBase::operator<(class cURLpp::OptionBase const &)const " (??MOptionBase@cURLpp@@UBE_NABV01@@Z)
urlReader.obj : error LNK2019: unresolved external symbol "public: enum cURL::CURLoption __thiscall cURLpp::OptionBase::getOption(void)const " (?getOption@OptionBase@cURLpp@@QBE?AW4CURLoption@cURL@@XZ) referenced in function "public: virtual void __thiscall cURLpp::Option<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >::print(void)const " (?print@?$Option@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@cURLpp@@UBEXXZ)
urlReader.obj : error LNK2019: unresolved external symbol "public: __thiscall cURLpp::UnsetOption::UnsetOption(char const *)" (??0UnsetOption@cURLpp@@QAE@PBD@Z) referenced in function "public: virtual void __thiscall cURLpp::Option<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >::updateMeToOption(class cURLpp::OptionBase const &)" (?updateMeToOption@?$Option@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@cURLpp@@UAEXABVOptionBase@2@@Z)
urlReader.obj : error LNK2019: unresolved external symbol "public: __thiscall cURLpp::UnsetOption::UnsetOption(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (??0UnsetOption@cURLpp@@QAE@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) referenced in function "private: virtual void __thiscall cURLpp::OptionTrait<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,10002>::updateHandleToMe(class cURLpp::CurlHandle *)const " (?updateHandleToMe@?$OptionTrait@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@$0CHBC@@cURLpp@@EBEXPAVCurlHandle@2@@Z)
urlReader.obj : error LNK2019: unresolved external symbol "public: __thiscall cURLpp::OptionBase::OptionBase(enum cURL::CURLoption)" (??0OptionBase@cURLpp@@QAE@W4CURLoption@cURL@@@Z) referenced in function "protected: __thiscall cURLpp::Option<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >::Option<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >(enum cURL::CURLoption,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (??0?$Option@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@cURLpp@@IAE@W4CURLoption@cURL@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)
urlReader.obj : error LNK2019: unresolved external symbol "void __cdecl cURLpp::libcurlRuntimeAssert(char const *,enum cURL::CURLcode)" (?libcurlRuntimeAssert@cURLpp@@YAXPBDW4CURLcode@cURL@@@Z) referenced in function "public: void __thiscall cURLpp::CurlHandle::option<char const *>(enum cURL::CURLoption,char const *)" (??$option@PBD@CurlHandle@cURLpp@@QAEXW4CURLoption@cURL@@PBD@Z)
Debug/test_project.dll : fatal error LNK1120: 15 unresolved externals

---

That's QUITE a mess.

All I'm doing is

cURLpp::initialize();
cURLpp::Easy curl_handle;
curl_handle.setOpt(cURLpp::Options::Url("http://www.example.com/"));

I haven't gone beyond there yet. I've clearly screwed something up with the linking because even with the first line, I get

Linking...
Creating library Debug/test_project.lib and object Debug/test_project.exp
urlReader.obj : error LNK2019: unresolved external symbol "void __cdecl cURLpp::initialize(long)" (?initialize@cURLpp@@YAXJ@Z) referenced in function "private: int __thiscall urlReader::saveData(void)" (?saveData@urlReader@@AAEHXZ)
Debug/test_project.dll : fatal error LNK1120: 1 unresolved externals

--

Can anybody shed some light? I'm a little new to C++.

Share this post


Link to post
Share on other sites
Quote:
Original post by RichardS
I suggest going the libcurl route. I've attached a really simple HTTP GET class. It should be easily modifiable to support HTTP POST or SSL, if that's what you need:

I decided to go the stateful route (only allowing the object to handle one download at a time) for 2 reasons: It allowed easy re-use of the CURL handle (which allows for pipelined transactions), and it allowed me to re-use buffers (so the user doesn't have to allocate their own entire buffer ahead of time, they just have to get a pointer). This has the downside of keeping a buffer around that's as large as the largest file you ever downloaded, but for my application, that doesn't matter. In my usage, almost all downloads will be about the same size, pipelineing is important, and the downloads will only be about ~1meg.

If all you're doing is reporting scores, then the buffer size should stay small, and it won't matter.

Obviously, the content/contentLength/contentType will be overwritten on each call to downloadFile().

HTTPDownloader.h:
*** Source Snippet Removed ***

HTTPDownloader.cpp
*** Source Snippet Removed ***


hello,

thank you for sharing your code. I tried it but as a result I don't get the code of a website but only a very long list of stupid signs...

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
How could I create an online server list in PHP, libcurl and C++? I need to store a table with The Name, type and IP address of every host in the table. The hosts need to be able to add/delete themselves and the clients need to see a list of IP addresses and names to go in a list box. How can I do that?

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
I've been informed that using stdout in PHP I could send the content of a MySQL database to a remote computer...but how do you read a stdout call from C++ in WinSock or RakNet?

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Could the CS 240 utiles be used instead of WinSock or RakNet?

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Could the CS 240 utilities be used instead of WinSock or RakNet?

Share this post


Link to post
Share on other sites
If you want a minimalist option, that you can compile straight into your code, try HTTP-GET. It's a simple C++ class that you just insert into your program, and tell it to go get a specific URL. It will return the response data to you when you ask for it.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
If I used That HTTP-GET class and used 'stdout' in PHP...would I use 'read()' untill complete() = true, or would I send a special value like "FINISHED_STREAM" with stdout when finished?

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
I don't know much about PHP...What would the code look like?
What would the cod be to read Variables like

servers.php?action=add?name=MyGame

and how would I add/remove a game to/from a MySQL table with IP address and game type and name?

Share this post


Link to post
Share on other sites

This topic is 4365 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this