Добрый день, товарищи!
Разбираюсь я с темой 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 нет, приходится изучать исходники.
Здравствуйте, silart, Вы писали:
S>Может я что-то делаю неправильно? Вменяемой документации на Pion Network Library нет, приходится изучать исходники.
На самом деле ничего не зависает, браузер просто ждет следующую порцию данных на все еще открытом соединении. Чтобы избежать этого необходимо завершить соединение.
void pion::tcp::connection::finish(void) [inline]
This function should be called when a server has finished handling the connection
Например вместо этого кода:
boost::shared_ptr<response_writer> writer = response_writer::create(connection, *request);
использовать такой:
boost::shared_ptr<response_writer> writer = response_writer::create(
connection, *request, boost::bind(&tcp::connection::finish, connection)
);
Здравствуйте, real_sba, Вы писали:
_>Здравствуйте, silart, Вы писали:
S>>Может я что-то делаю неправильно? Вменяемой документации на Pion Network Library нет, приходится изучать исходники.
_>На самом деле ничего не зависает, браузер просто ждет следующую порцию данных на все еще открытом соединении. Чтобы избежать этого необходимо завершить соединение.
_>_>void pion::tcp::connection::finish(void) [inline]
_>This function should be called when a server has finished handling the connection
_>
_>Например вместо этого кода:_>boost::shared_ptr<response_writer> writer = response_writer::create(connection, *request);
_>
использовать такой:_>boost::shared_ptr<response_writer> writer = response_writer::create(
_> connection, *request, boost::bind(&tcp::connection::finish, connection)
_>);
_>
Спасибо! В этом была моя проблема.
Вы случайно не знаете, можно ли изменить название темы? Я бы хотел здесь задавать вопросы по работе с Pion Network Library.