4
// $Id: //poco/1.2/Net/samples/HTTPLoadTest/src/HTTPLoadTest.cpp#1 $
6
// This sample demonstrates the HTTPClientSession class.
8
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
11
// Permission is hereby granted, free of charge, to any person or organization
12
// obtaining a copy of the software and accompanying documentation covered by
13
// this license (the "Software") to use, reproduce, display, distribute,
14
// execute, and transmit the Software, and to prepare derivative works of the
15
// Software, and to permit third-parties to whom the Software is furnished to
16
// do so, all subject to the following:
18
// The copyright notices in the Software and this entire statement, including
19
// the above license grant, this restriction and the following disclaimer,
20
// must be included in all copies of the Software, in whole or in part, and
21
// all derivative works of the Software, unless such copies or derivative
22
// works are solely in the form of machine-executable object code generated by
23
// a source language processor.
25
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
28
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
29
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
30
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
31
// DEALINGS IN THE SOFTWARE.
35
#include "Poco/Net/HTTPClientSession.h"
36
#include "Poco/Net/HTTPRequest.h"
37
#include "Poco/Net/HTTPResponse.h"
38
#include "Poco/Net/HTTPCookie.h"
39
#include "Poco/Net/NameValueCollection.h"
40
#include "Poco/Path.h"
42
#include "Poco/AutoPtr.h"
43
#include "Poco/Thread.h"
44
#include "Poco/Mutex.h"
45
#include "Poco/Runnable.h"
46
#include "Poco/Stopwatch.h"
47
#include "Poco/NumberParser.h"
48
#include "Poco/Exception.h"
49
#include "Poco/Util/Application.h"
50
#include "Poco/Util/Option.h"
51
#include "Poco/Util/OptionSet.h"
52
#include "Poco/Util/HelpFormatter.h"
53
#include "Poco/Util/AbstractConfiguration.h"
57
using Poco::Net::HTTPClientSession;
58
using Poco::Net::HTTPRequest;
59
using Poco::Net::HTTPResponse;
60
using Poco::Net::HTTPMessage;
61
using Poco::Net::HTTPCookie;
62
using Poco::Net::NameValueCollection;
63
using Poco::Util::Application;
64
using Poco::Util::Option;
65
using Poco::Util::OptionSet;
66
using Poco::Util::HelpFormatter;
67
using Poco::Util::AbstractConfiguration;
70
using Poco::FastMutex;
72
using Poco::Stopwatch;
73
using Poco::NumberParser;
76
using Poco::Exception;
78
class HTTPClient : public Runnable
81
HTTPClient(const URI& uri, int repetitions, bool cookies=false, bool verbose=false):
85
_repetitions(repetitions),
89
_gRepetitions += _repetitions;
99
std::vector<HTTPCookie> cookies;
101
for (int i = 0; i < _repetitions; ++i)
106
std::string path(_uri.getPathAndQuery());
107
if (path.empty()) path = "/";
109
HTTPClientSession session(_uri.getHost(), _uri.getPort());
110
HTTPRequest req(HTTPRequest::HTTP_GET, path, HTTPMessage::HTTP_1_1);
114
NameValueCollection nvc;
115
std::vector<HTTPCookie>::iterator it = cookies.begin();
116
for(; it != cookies.end(); ++it)
117
nvc.add((*it).getName(), (*it).getValue());
124
session.sendRequest(req);
125
std::istream& rs = session.receiveResponse(res);
127
_success += HTTPResponse::HTTP_OK == res.getStatus() ? 1 : 0;
128
if (_cookies) res.getCookies(cookies);
133
FastMutex::ScopedLock lock(_mutex);
135
<< _uri.toString() << ' ' << res.getStatus() << ' ' << res.getReason()
136
<< ' ' << usec/1000.0 << "ms" << std::endl;
141
catch (Exception& exc)
143
FastMutex::ScopedLock lock(_mutex);
144
std::cerr << exc.displayText() << std::endl;
149
FastMutex::ScopedLock lock(_mutex);
150
_gSuccess += _success;
154
printStats(_uri.toString(), _repetitions, _success, _usec);
157
static void printStats(std::string uri, int repetitions, int success, Poco::UInt64 usec);
158
static int totalAttempts();
159
static Poco::UInt64 totalMicroseconds();
160
static int totalSuccessCount();
171
static int _gRepetitions;
172
static Poco::UInt64 _gUsec;
173
static int _gSuccess;
174
static FastMutex _mutex;
177
FastMutex HTTPClient::_mutex;
178
int HTTPClient::_gRepetitions;
179
Poco::UInt64 HTTPClient::_gUsec;
180
int HTTPClient::_gSuccess;
182
int HTTPClient::totalAttempts()
184
return _gRepetitions;
187
Poco::UInt64 HTTPClient::totalMicroseconds()
192
int HTTPClient::totalSuccessCount()
197
void HTTPClient::printStats(std::string uri, int repetitions, int success, Poco::UInt64 usec)
199
FastMutex::ScopedLock lock(_mutex);
201
std::cout << std::endl << "--------------" << std::endl
202
<< "Statistics for " << uri << std::endl << "--------------"
204
<< repetitions << " attempts, " << success << " succesful ("
205
<< ((float) success / (float) repetitions) * 100.0 << "%)" << std::endl
206
<< "Avg response time: " << ((float) usec / (float) repetitions) / 1000.0 << "ms, " << std::endl
207
<< "Avg requests/second handled: " << ((float) success /((float) usec / 1000000.0)) << std::endl
208
<< "Total time: " << (float) usec / 1000000.0 << std::endl;
211
class HTTPLoadTest: public Application
212
/// This sample demonstrates some of the features of the Poco::Util::Application class,
213
/// such as configuration file handling and command line arguments processing.
215
/// Try HTTPLoadTest --help (on Unix platforms) or HTTPLoadTest /help (elsewhere) for
216
/// more information.
220
_helpRequested(false),
229
void initialize(Application& self)
231
loadConfiguration(); // load default configuration files, if present
232
Application::initialize(self);
233
// add your own initialization code here
238
// add your own uninitialization code here
239
Application::uninitialize();
242
void reinitialize(Application& self)
244
Application::reinitialize(self);
245
// add your own reinitialization code here
248
void defineOptions(OptionSet& options)
250
Application::defineOptions(options);
253
Option("help", "h", "display help information on command line arguments")
258
Option("verbose", "v", "display messages on stdout")
263
Option("cookies", "c", "resend cookies")
268
Option("uri", "u", "HTTP URI")
274
Option("repetitions", "r", "fetch repetitions")
277
.argument("repetitions"));
280
Option("threads", "t", "thread count")
283
.argument("threads"));
286
void handleOption(const std::string& name, const std::string& value)
288
Application::handleOption(name, value);
291
_helpRequested = true;
292
else if (name == "verbose")
294
else if (name == "cookies")
296
else if (name == "uri")
298
else if (name == "repetitions")
299
_repetitions = NumberParser::parse(value);
300
else if (name == "threads")
301
_threads = NumberParser::parse(value);
306
HelpFormatter helpFormatter(options());
307
helpFormatter.setCommand(commandName());
308
helpFormatter.setUsage("OPTIONS");
309
helpFormatter.setHeader("A sample application that demonstrates some of the features of the Poco::Util::Application class.");
310
helpFormatter.format(std::cout);
313
void defineProperty(const std::string& def)
317
std::string::size_type pos = def.find('=');
318
if (pos != std::string::npos)
320
name.assign(def, 0, pos);
321
value.assign(def, pos + 1, def.length() - pos);
324
config().setString(name, value);
327
int main(const std::vector<std::string>& args)
336
std::vector<Thread*> threads;
340
for (int i = 0; i < _threads; ++i)
342
Thread* pt = new Thread(_uri);
344
threads.push_back(pt);
345
HTTPClient* pHTTPClient = new HTTPClient(uri, _repetitions, _cookies, _verbose);
346
poco_check_ptr(pHTTPClient);
347
threads.back()->start(*pHTTPClient);
350
std::vector<Thread*>::iterator it = threads.begin();
351
for(; it != threads.end(); ++it)
358
HTTPClient::printStats(_uri, HTTPClient::totalAttempts(), HTTPClient::totalSuccessCount(), sw.elapsed());
361
return Application::EXIT_OK;
374
int main(int argc, char** argv)
376
AutoPtr<HTTPLoadTest> pApp = new HTTPLoadTest;
379
pApp->init(argc, argv);
381
catch (Poco::Exception& exc)
383
pApp->logger().log(exc);
384
return Application::EXIT_CONFIG;