Description: The below demonstrates the usage of thread local storages. It uses boost's implementation of thread local storage. The program creates mulitple thread which sends mulitple HTTP requests using libcurl. In order for each thread to use a single connection to send HTTP requests, each thread should have a single CURL handle. Each thread creates his own handle in his local storage.
Progaram:
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <curl/curl.h>
#include <boost/thread/tss.hpp>
#include <iostream>
using namespace std;
class HTTPHandle
{
private:
CURL* curl;
public:
HTTPHandle()
{
cout << "Creating curl easy handle" << endl;
curl = curl_easy_init();
}
CURL* getHandle()
{
return curl;
}
~HTTPHandle()
{
cout << "Cleaning up easy handle" << endl;
curl_easy_cleanup(curl);
}
};
void destroyHttpHandle(HTTPHandle* ptr)
{
delete ptr;
}
void makeRequest()
{
#include <unistd.h>
#include <pthread.h>
#include <curl/curl.h>
#include <boost/thread/tss.hpp>
#include <iostream>
using namespace std;
class HTTPHandle
{
private:
CURL* curl;
public:
HTTPHandle()
{
cout << "Creating curl easy handle" << endl;
curl = curl_easy_init();
}
CURL* getHandle()
{
return curl;
}
~HTTPHandle()
{
cout << "Cleaning up easy handle" << endl;
curl_easy_cleanup(curl);
}
};
void destroyHttpHandle(HTTPHandle* ptr)
{
delete ptr;
}
void makeRequest()
{
//We cannote directly create instance of CURL since it is defined as 'typedef CURL void;'
static boost::thread_specific_ptr<HTTPHandle> instance(destroyHttpHandle);
// Create new HTTPHandle object if not already created one for this thread
if(! instance.get())
{
instance.reset(new HTTPHandle);
}
CURL* curl = instance->getHandle();
CURLcode res;
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "http://10.10.0.1");
// example.com is redirected, so we tell libcurl to follow redirection
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
// Perform the request, res will get the return code
res = curl_easy_perform(curl);
// Check for errors
if(res != CURLE_OK)
cerr << "curl_easy_perform() failed:" << curl_easy_strerror(res) << endl;
}
}
static boost::thread_specific_ptr<HTTPHandle> instance(destroyHttpHandle);
// Create new HTTPHandle object if not already created one for this thread
if(! instance.get())
{
instance.reset(new HTTPHandle);
}
CURL* curl = instance->getHandle();
CURLcode res;
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "http://10.10.0.1");
// example.com is redirected, so we tell libcurl to follow redirection
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
// Perform the request, res will get the return code
res = curl_easy_perform(curl);
// Check for errors
if(res != CURLE_OK)
cerr << "curl_easy_perform() failed:" << curl_easy_strerror(res) << endl;
}
}
// Starting point of thread. Makes two HTTP request
void* thread_func(void* arg)
{
for(int i = 1; i <= 2; i++)
{
makeRequest();
}
pthread_exit(NULL);
}
void* thread_func(void* arg)
{
for(int i = 1; i <= 2; i++)
{
makeRequest();
}
pthread_exit(NULL);
}
int main(void)
{
pthread_t thread1, thread2;
cout << "Global curl init." << endl;
{
pthread_t thread1, thread2;
cout << "Global curl init." << endl;
//initialize libcurl
curl_global_init(CURL_GLOBAL_ALL);
//Start two threads.
pthread_create(&thread1, NULL, thread_func, NULL);
pthread_create(&thread2, NULL, thread_func, NULL);
// Wait for two threads to finish
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
// Two threads completed. Each would have made two HTTP requests. No. of connection to 10.10.0.1 would be only two.
// Since each thread creates only one curl handle. Check this using 'netstat -nap | grep 10.10.0.1'
cout << "Check output of 'netstat -nap | grep 10.10.0.1'" << endl;
sleep(5);
cout << "Global curl cleanup." << endl;
// global libcurl cleanup
curl_global_cleanup();
}
Output:
Global curl init.
Creating curl easy handle
Creating curl easy handle
Cleaning up easy handle
Creating curl easy handle
Creating curl easy handle
Cleaning up easy handle
Cleaning up easy handle
Check output of 'netstat -nap | grep 10.10.0.1'
Global curl cleanup.
Global curl cleanup.
[root@localhost curl]# netstat -nap | grep 10.223.3.131
tcp 0 0 10.223.3.171:45511 10.10.0.1:80 TIME_WAIT -
tcp 0 0 10.223.3.171:45512 10.10.0.1:80 TIME_WAIT -
tcp 0 0 10.223.3.171:45511 10.10.0.1:80 TIME_WAIT -
tcp 0 0 10.223.3.171:45512 10.10.0.1:80 TIME_WAIT -
No comments:
Post a Comment