Jump to content
  • Advertisement
Sign in to follow this  
Rob Loach

[web] C++ HTTP Requests

This topic is 4674 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
Advertisement
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
No other alternatives? I have yet to try either out completely, but will get to it sometime.... Anyone have any other suggestions?

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
Guest Anonymous Poster
[google]

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!