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 нет, приходится изучать исходники.
Re: pion, boost asio есть некоторые проблемы
От: real_sba http://cellwar.xyz/
Дата: 07.07.14 09:34
Оценка:
Здравствуйте, 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)
);
Re[2]: pion, boost asio есть некоторые проблемы
От: silart  
Дата: 07.07.14 12:25
Оценка:
Здравствуйте, 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.
Re[3]: pion, boost asio есть некоторые проблемы
От: real_sba http://cellwar.xyz/
Дата: 07.07.14 13:20
Оценка:
Здравствуйте, silart, Вы писали:

S>Спасибо! В этом была моя проблема.

Пожалуйста.

S>Вы случайно не знаете, можно ли изменить название темы? Я бы хотел здесь задавать вопросы по работе с Pion Network Library.

Без понятия как менять название темы. Полагаю лучше каждый вопрос оформлять отдельно и полноценно.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.