pion, boost asio есть некоторые проблемы
От: silart  
Дата: 07.07.14 07:27
Оценка:
Добрый день, товарищи!

Разбираюсь я с темой 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 нет, приходится изучать исходники.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.