Добрый день, товарищи!
Разбираюсь я с темой http-сервера на C++. Решил воспользоваться Pion Network Library.
Есть простой http-сервер, у которого имеется 3 ресурса, очень простые html страницы.
#include <pion/scheduler.hpp>
#include <pion/http/server.hpp>
#include <pion/http/response_writer.hpp>
#include <pion/scheduler.hpp>
#include <boost/bind.hpp>
#include <iostream>
#include <sstream>
class Server
: public pion::http::server
{
private:
void OnGetRequest(pion::http::request_ptr& request, pion::tcp::connection_ptr& connection);
public:
Server(pion::scheduler& sched, const unsigned int port)
: pion::http::server(sched, port)
{}
void init();
};
void Server::init()
{
add_resource("/", boost::bind(&Server::OnGetRequest, this, _1, _2) );
add_resource("/week_days", boost::bind(&Server::OnGetRequest, this, _1, _2) );
add_resource("/months", boost::bind(&Server::OnGetRequest, this, _1, _2) );
}
void Server::OnGetRequest( pion::http::request_ptr& request, pion::tcp::connection_ptr& connection )
{
using namespace pion::http;
using namespace std;
if (request->get_resource() == "/")
{
ostringstream oss;
oss << "<html><head><meta charset=\"utf-8\"><title>Main page</title></head>";
oss << "<body><title>Main page:</title><h1 align=center>Main page:</h1>";
oss << "<p><a href=\"./months\">" << "Month" << "</a></p>";
oss << "<p><a href=\"./week_days\">" << "Week days" << "</a></p>";
oss << "</body></html>";
boost::shared_ptr<response_writer> writer = response_writer::create(connection, *request);
writer->write( oss.str() );
response& r = writer->get_response();
r.set_status_code(types::RESPONSE_CODE_OK);
r.set_status_message(types::RESPONSE_MESSAGE_OK);
writer->send();
}
else
if (request->get_resource() == "/week_days")
{
ostringstream oss;
oss << "<html><head><meta charset=\"utf-8\"><title>Week days</title></head>";
oss << "<body><title>Week days:</title><h1 align=center>Week days:</h1>";
oss << "<p>" << "Monday" << "</p>";
oss << "<p>" << "Tuesday" << "</p>";
oss << "<p>" << "Wednesday" << "</p>";
oss << "<p>" << "Thursday" << "</p>";
oss << "<p>" << "Friday" << "</p>";
oss << "<p>" << "Saturday" << "</p>";
oss << "<p>" << "Sunday" << "</p>";
oss << "</body></html>";
boost::shared_ptr<response_writer> writer = response_writer::create(connection, *request);
writer->write( oss.str() );
response& r = writer->get_response();
r.set_status_code(types::RESPONSE_CODE_OK);
r.set_status_message(types::RESPONSE_MESSAGE_OK);
writer->send();
}
else
if (request->get_resource() == "/months")
{
ostringstream oss;
oss << "<html><head><meta charset=\"utf-8\"><title>Months</title></head>";
oss << "<body><title>Months:</title><h1 align=center>Months:</h1>";
oss << "<p>" << "January" << "</p>";
oss << "<p>" << "February" << "</p>";
oss << "<p>" << "March" << "</p>";
oss << "<p>" << "April" << "</p>";
oss << "<p>" << "May" << "</p>";
oss << "<p>" << "June" << "</p>";
oss << "<p>" << "July" << "</p>";
oss << "<p>" << "August" << "</p>";
oss << "<p>" << "September" << "</p>";
oss << "<p>" << "October" << "</p>";
oss << "<p>" << "November" << "</p>";
oss << "<p>" << "December" << "</p>";
oss << "</body></html>";
boost::shared_ptr<response_writer> writer = response_writer::create(connection, *request);
writer->write( oss.str() );
response& r = writer->get_response();
r.set_status_code(types::RESPONSE_CODE_OK);
r.set_status_message(types::RESPONSE_MESSAGE_OK);
writer->send();
}
}
int main()
{
using namespace std;
pion::single_service_scheduler scheduler;
scheduler.set_num_threads(4);
Server msvr(scheduler, 80);
msvr.init();
msvr.start();
scheduler.join();
return 0;
}
Не знаю, баг это или фича.
Суть в следующем:
Если запустить данный вебсервер, а потом обраниться к нему браузером, наблюдаем такой эффект: при первом обращении, страница загружается мгновенно, однако при последующих обращениях происходит зависание. То есть если кликнуть на гиперссылку, браузер начинает подвисать и страницы нет, если кликнуть еще раз, то страница загрузится. То есть страницы почему-то загружаются только после повторных кликов (при том что я один пользователь). Тоже самое происходит с запросами POST. Если нажать на кнопку, которая отправляет этот запрос, использую javascript, то он не доходит. Нажимаем повторно, приходит сразу два запроса POST. Такое впечатление, что сервер засыпает, если нет к нему обращений. Если же обращения есть, описанного эффекта не наблюдается.
Эффект наблюдается в Windows и в Linux.
В Windows было выяснено, что зависание происходит в недрах boost asio в файле win_iocp_io_service.ipp в следующей строке:
...
BOOL ok = ::GetQueuedCompletionStatus(iocp_.handle, &bytes_transferred,
&completion_key, &overlapped, block ? gqcs_timeout : 0);
...
Тестирование производилось 32 разрядной сборки вышеприведенного кода:
— Windows 7 x64
— Windows XP
— Linux Mint Debian x86
Использовалось MSVS 2012, boost 1.55, pion 5.0.6
Может я что-то делаю неправильно? Вменяемой документации на Pion Network Library нет, приходится изучать исходники.