LinuxQuestions.org
Share your knowledge at the LQ Wiki.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 01-08-2008, 10:07 AM   #1
taylor_venable
Member
 
Registered: Jun 2005
Location: Indiana, USA
Distribution: OpenBSD, Ubuntu
Posts: 892

Rep: Reputation: 43
C++ libcurl multi data lossage


I'm pretty sure this is just my fault as a programmer, but I cannot see the flaw. I'm using libcurl's multi interface to talk to a server, emulating multiple simultaneous clients. Each client is represented by a C++ "request" object. One member of the object is a ostringstream into which the libcurl write function will put its data. However, after multi_perform is finished, no data is in the ostringstream.

Code:
class request {
    private:
        std::string* url;
        std::ostringstream* content_stream;

        std::string* content;
        long code;
        double time;

        CURL* easy_handle;
        CURLM* multi_handle;
        struct curl_slist* headers;

    public:
        request(CURLM* multi_handle, const char* method) {
            this->url = new std::string((boost::format("%s?method=%s") % JSON_RPC_TUNNEL % method).str());
            this->multi_handle = multi_handle;
            this->headers = NULL;
        }

        /*
         * CURL callback function to write output into a stream.
         */
        static size_t write_function(void* buffer, size_t size, size_t count, void* stream) {
            static_cast<std::ostream*>(stream)->write(static_cast<const char*>(buffer), count);
            return count;
        }

        void do_request(const char* json) {
            this->easy_handle = curl_easy_init();
            this->content_stream = new std::ostringstream();

            // handle the content-type header
            headers = curl_slist_append(headers, "Content-Type: application/json");
            curl_easy_setopt(this->easy_handle, CURLOPT_HTTPHEADER, headers);

            // set the data to upload
            curl_easy_setopt(this->easy_handle, CURLOPT_POSTFIELDS, json);
            curl_easy_setopt(this->easy_handle, CURLOPT_POSTFIELDSIZE, std::strlen(json));

            // set more options
            curl_easy_setopt(this->easy_handle, CURLOPT_URL, url->c_str());
            curl_easy_setopt(this->easy_handle, CURLOPT_VERBOSE, true);

            // set the write-back information
            curl_easy_setopt(this->easy_handle, CURLOPT_WRITEFUNCTION, &request::write_function);
            curl_easy_setopt(this->easy_handle, CURLOPT_WRITEDATA, content_stream);

            // curl_easy_perform(easy_handle);
            curl_multi_add_handle(this->multi_handle, easy_handle);
        }

        void extract_results() {
            this->content = new std::string(content_stream->str());
            curl_easy_getinfo(this->easy_handle, CURLINFO_RESPONSE_CODE, &(this->code));
            curl_easy_getinfo(this->easy_handle, CURLINFO_TOTAL_TIME, &(this->time));
        }

        ~request() {
            delete this->url;
            delete this->content_stream;
            delete this->content;
            curl_slist_free_all(this->headers);
            curl_easy_cleanup(this->easy_handle);
        }
};
Code:
class client {
    private:
        unsigned int id;
        request* r;

    public:
        client(int id) {
            this->id = id;
        }

        ~client() {
            delete this->r;
        }

        unsigned int get_id() {
            return this->id;
        }

        void do_request(CURLM* multi_handle, const char* method, const char* json) {
            this->r = new request(multi_handle, method);
            this->r->do_request(json);
        }

        request* get_request() {
            return this->r;
        }
};
Code:
int main(int argc, char** argv) {
    curl_global_init(CURL_GLOBAL_SSL);

    client* c[MAX_THREADS];
    for (unsigned int i = 0; i < MAX_THREADS; i += 1) {
        c[i] = new client(i);
    }

    CURLM* multi_handle = curl_multi_init();
    for (unsigned int i = 0; i < MAX_THREADS; i += 1) {
        phase_one(multi_handle, c[i]);
    }

    int completed = 0;
    int completed_total = 0;

    while (completed_total < MAX_THREADS) {
        curl_multi_perform(multi_handle, &completed);
        completed_total += completed;
        completed = 0;
    }

    for (unsigned int i = 0; i < MAX_THREADS; i += 1) {
        result r;
        c[i]->get_request()->extract_results();
        phase_two(c[i], &r);
        std::cerr << r << std::endl;
    }

    curl_multi_cleanup(multi_handle);
    curl_global_cleanup();

    return 0;
}
Here, the function phase_one() sets up the data that will be sent to the server, calling do_request on the client object, which sets up the request and registers to the multi handle. Then the multi is performed. Lastly, phase_two() has the request take the data (like HTTP response code and content) from its easy handle and from the ostringstream. Only, nothing ever comes back, and the values of the HTTP code and time remain unchanged.

So, in short, it seems not to work! The data that should be available is not, and I can assure that the curl request is correct as it works fine when performing the easy handle. I think, therefore, it must be a scope or memory problem, perhaps. If anybody has any ideas, I greatly appreciate it.
 
Old 01-09-2008, 04:00 PM   #2
osor
HCL Maintainer
 
Registered: Jan 2006
Distribution: (H)LFS, Gentoo
Posts: 2,450

Rep: Reputation: 78
What is result supposed to be? A class or a typedef? It might be helpful if you gave us more code (perhaps a tarball on your website).
 
  


Reply

Tags
c++



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Libcurl Problem SlacUser Slackware 6 05-09-2007 05:39 PM
Can a JTable display multi-level data? paulsm4 Programming 4 05-09-2006 06:44 PM
libcurl.so.2 liljhand Linux - Newbie 3 01-24-2005 07:17 PM
Why is libcurl not being found? maestro52 Fedora 7 12-23-2004 12:19 PM
libcurl.so.2 in FC3 robyduck Fedora 3 12-08-2004 02:22 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 06:04 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration