BOOST.ASIO
От: paxerus  
Дата: 21.05.10 09:31
Оценка:
Добрый день
Начал изучать Boost Asio
нашел один примерчик сервера с пулом потоков,немного его переделал . и у меня в нем ошибка возникает когда клиент шлет данные и сервер пытается возвратить ответ возникает ошибка
http://files.rsdn.ru/83044/Server.7z
http://files.rsdn.ru/83044/threadpool-0_2_5-src.zip это доп библиотека (компилить не нужно,ток хидеры привязать)

вот простенький проект на VS8 посмотрите пожалуйста что не так
пишу так возникает ошибка
std::string answer("ertertertertertert");
                ba::async_write(socket_,ba::buffer(answer),
                        boost::bind(&connection::SendAnswer,
                                        shared_from_this()));


пишу так

                ba::async_write(socket_,ba::buffer("ertertertertertert"),
                        boost::bind(&connection::SendAnswer,
                                        shared_from_this()));


нормально проходит
заранее спасибо
boost asio boost::asio
Re: BOOST.ASIO
От: in trance Россия  
Дата: 21.05.10 09:56
Оценка:
Здравствуйте, paxerus, Вы писали:

P>пишу так возникает ошибка

P>
P>std::string answer("ertertertertertert");
P>                ba::async_write(socket_,ba::buffer(answer),
P>                        boost::bind(&connection::SendAnswer,
P>                                        shared_from_this()));
P>


Исходники не смотрел, но судя по всему answer долго не живет, т.е. вызывается деструктор раньше, чем asio отправляет данные. Сделай его как мембер класса.
Re[2]: BOOST.ASIO
От: paxerus  
Дата: 21.05.10 10:10
Оценка:
Здравствуйте, in trance, Вы писали:

IT>Здравствуйте, paxerus, Вы писали:


P>>пишу так возникает ошибка

P>>
P>>std::string answer("ertertertertertert");
P>>                ba::async_write(socket_,ba::buffer(answer),
P>>                        boost::bind(&connection::SendAnswer,
P>>                                        shared_from_this()));
P>>


IT>Исходники не смотрел, но судя по всему answer долго не живет, т.е. вызывается деструктор раньше, чем asio отправляет данные. Сделай его как мембер класса.


так и думал что из за этого но такое простое решение как засунуть в класс не пришло в мою голову спасибо стало нормально ,еще один вопрос есть
не буду мучать скачанием исходника, поэтому кусочек кода выложу тут


void connection::ReciveHeader(const bs::error_code& err, size_t len)
{    if(!err)
    {
                answer="ertertertertertert";
                ba::async_write(socket_,ba::buffer(answer),
                        boost::bind(&connection::SendAnswer,
                                        shared_from_this()));

   }

}
void connection::SendAnswer()
{    socket_.close();
    shared_from_this().reset();
}

void connection::run() 
{

    try 
    {
              async_read(socket_, ba::buffer(HeaderBuff), ba::transfer_at_least(1),
               boost::bind(&connection::ReciveHeader,
                           shared_from_this(),
                           ba::placeholders::error,
                           ba::placeholders::bytes_transferred));
                    

    } catch(std::exception& x) {
        
    //        std::cerr << "Exception: " << x.what() << std::endl;
        }
    }


меня волнует нормально будет если я

socket_.close();
shared_from_this().reset();

расположу в функции SendAnswer ???
Re[3]: BOOST.ASIO
От: uzhas Ниоткуда  
Дата: 21.05.10 13:44
Оценка:
Здравствуйте, paxerus, Вы писали:
shared_from_this().reset();


я что-то не понимаю, да?
Re[4]: BOOST.ASIO
От: paxerus  
Дата: 23.05.10 05:09
Оценка:
Здравствуйте, uzhas, Вы писали:

U>Здравствуйте, paxerus, Вы писали:

U>
U>shared_from_this().reset();
U>


U>я что-то не понимаю, да?


ну не нужно смеятся я же говорю что изучаю так сказать , лучшеб объяснили что и как и зачем
Re[4]: BOOST.ASIO
От: Хвост  
Дата: 23.05.10 11:20
Оценка: +1 :)
Здравствуйте, uzhas, Вы писали:

U>Здравствуйте, paxerus, Вы писали:

U>
U>shared_from_this().reset();
U>


U>я что-то не понимаю, да?

nop 21-го века.
People write code, programming languages don't.
Re[5]: BOOST.ASIO
От: ArtDenis Россия  
Дата: 24.05.10 13:06
Оценка:
Здравствуйте, Хвост, Вы писали:

Х>nop 21-го века.


Блин, я также хотел написать
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Re[6]: BOOST.ASIO
От: paxerus  
Дата: 24.05.10 17:42
Оценка:
Здравствуйте, ArtDenis, Вы писали:

AD>Здравствуйте, Хвост, Вы писали:


Х>>nop 21-го века.


AD>Блин, я также хотел написать

я так понял пофлудить все горазды, а как что дельное сказать так....
Re[7]: BOOST.ASIO
От: _pilgrim  
Дата: 24.05.10 23:36
Оценка: 3 (1)
Здравствуйте, paxerus, Вы писали:

P>я так понял пофлудить все горазды, а как что дельное сказать так....


Судя по иcпользованию метода shared_from_this, тип вашего объекта наследует от enable_shared_from_this. Такое наследование как правило нужно в случаях, когда из instance-метода необходимо передать shared_ptr, указывающий на текущий объект, во внешний метод\функцию.
Необходимым условием для этого (получение shared_ptr вызовом shared_from_this()) является наличие внешнего shared_ptr на ваш объект, т.е. "где-то" уже должен существовать shared_ptr, "владеющий" вашим объектом.

Касаемо кода
shared_from_this().reset();


вызов shared_from_this создает новый shared_ptr (внутренний, разделяемый между всеми экземплярами shared_ptr владеющими вашим объектом, счетчик которого >= 2, т.к. по крайней мере один shared_ptr уже ссылается на объект), у которого затем сбрасывается указатель на объект (и соотв. значение счетчика уменьшается на 1), т.е. полезный выхлоп от этого кода нулевой

Т.о., если вам нужно, чтобы объект жил пока идут асинхронные операции чтения\записи, и не держать при этом ссылку на объект где-нибудь еще, достаточно создать экземпляр объекта, инициализировать им shared_ptr и передать управлению вашему объекту, который будет "протаскивать" shared_ptr объекта (с пом. shared_from_this) через вызовы async_read\write методов asio, после вызова последнего read\write обработчика объект будет удален (конечно если нет других shared_ptr, кроме тех, которые переданы в методы async_read\write)
напр:

shared_ptr<connection> conn(new connection(...));
conn->run(); //асинхронный метод, connection сам отвечает за свое время жизни, передавая shared_ptr на себя в методы asio


ps: имхо, описанный выше подход ("самоуправление" жизнью соединения) хоть и имеет право на жизнь, но не очень юзабелен, т.к. может потребоваться вести учет соединений, управлять их количеством, убивать "зависшие соединения" и тд, т.е. осуществлять управление соединениями.
Re[8]: BOOST.ASIO
От: paxerus  
Дата: 31.05.10 05:53
Оценка:
Здравствуйте, _pilgrim, Вы писали:

_>Здравствуйте, paxerus, Вы писали:


P>>я так понял пофлудить все горазды, а как что дельное сказать так....


_>Судя по иcпользованию метода shared_from_this, тип вашего объекта наследует от enable_shared_from_this. Такое наследование как правило нужно в случаях, когда из instance-метода необходимо передать shared_ptr, указывающий на текущий объект, во внешний метод\функцию.

_>Необходимым условием для этого (получение shared_ptr вызовом shared_from_this()) является наличие внешнего shared_ptr на ваш объект, т.е. "где-то" уже должен существовать shared_ptr, "владеющий" вашим объектом.

_>Касаемо кода

_>
_>shared_from_this().reset();
_>


_>вызов shared_from_this создает новый shared_ptr (внутренний, разделяемый между всеми экземплярами shared_ptr владеющими вашим объектом, счетчик которого >= 2, т.к. по крайней мере один shared_ptr уже ссылается на объект), у которого затем сбрасывается указатель на объект (и соотв. значение счетчика уменьшается на 1), т.е. полезный выхлоп от этого кода нулевой


_>Т.о., если вам нужно, чтобы объект жил пока идут асинхронные операции чтения\записи, и не держать при этом ссылку на объект где-нибудь еще, достаточно создать экземпляр объекта, инициализировать им shared_ptr и передать управлению вашему объекту, который будет "протаскивать" shared_ptr объекта (с пом. shared_from_this) через вызовы async_read\write методов asio, после вызова последнего read\write обработчика объект будет удален (конечно если нет других shared_ptr, кроме тех, которые переданы в методы async_read\write)

_>напр:

_>
_>shared_ptr<connection> conn(new connection(...));
conn->>run(); //асинхронный метод, connection сам отвечает за свое время жизни, передавая shared_ptr на себя в методы asio
_>


_>ps: имхо, описанный выше подход ("самоуправление" жизнью соединения) хоть и имеет право на жизнь, но не очень юзабелен, т.к. может потребоваться вести учет соединений, управлять их количеством, убивать "зависшие соединения" и тд, т.е. осуществлять управление соединениями.


Спасибо за разъяснения, а как тогда правильно делать? я так понимаю shared_from_this() нужно только чтоб соединение не завершиломь пока жив shared_from_this() правильно?

еще такая проблема наприсовалась :

у меня сервер является dll — плагином к другому серверу
и почему то происходит ошибка, пример кода ниже
class CSession
{....        
  public:
        CSession(){}
                UINT64                    SessionId;
        ExternalStruct                      s_us;                   //структура из внешнего приложения,ее описание в общем хидере
....
};
class connection : public boost::enable_shared_from_this<connection> {
public:
        ....
    typedef boost::ptr_map<UINT64,CSession>    SessionMap;  
        SessionMap                 ses_map; 
    ba::io_service&            io_service_;   
        ba::ip::tcp::socket        socket_; 
        boost::array<unsigned char, 8192>Buff; 
        ExternalSrv                 *extsrv;
    
   void run();
   void Recive(const bs::error_code& err, size_t len,size_t body_lenght);
  ....  
   CSession* create_ses(UINT64 ses_id) {
            ses_map.insert(ses_id,new CSession());
        return &ses_map[ses_id];
    }
 
   void delete_ses(UINT64 ses_id) {
       try{
            SessionMap::iterator it=ses_map.find(ses_id);
            if(&it!=NULL)      
               ses_map.erase(it);
         }
      catch(...){}
...
   }

void connection::run() 
{

    try 
    {
             
        async_read(socket_, ba::buffer(Buff), ba::transfer_at_least(9),
               boost::bind(&connection::Recive,
                           shared_from_this(),
                           ba::placeholders::error,
                           ba::placeholders::bytes_transferred,9));                

    } catch(std::exception& x) {
        
            std::cerr << "Exception: " << x.what() << std::endl;
        }
}

 void connection::Recive(const bs::error_code& err, size_t len,size_t body_lenght)
{
      CSession *ses= create_ses(123456);
      ses->SessionId=123456;
      //если делать  delete_ses(123456);тут то все нормально
      extsrv->ExternalFunc(&ses->s_us);

      delete_ses(123456); ----->а тут error

}


Во внешней функции происходит примерно следующее


void ExternalFunc(ExternalStruct  &s_us)
{
    ExternalStruct st; // в структуре в основном char и int естесно все статическое

    st.field =123;

    s_us=st;
}


При вызове delete_ses происходит ошибка
ругается на это
__CLR_OR_THIS_CALL ~basic_string()
{ // destroy the string
_Tidy(true);
}

не понятно почему он вообще на это ругается
ведь в структуре вообще не используется std::string чисто сишная структура


очень прошу помочь
Re: BOOST.ASIO
От: paxerus  
Дата: 08.06.10 03:02
Оценка:
UP
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.