Модераторы: feodorv

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> boost::asio 
V
    Опции темы
Kirgston
Дата 28.2.2011, 12:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 792
Регистрация: 24.12.2007

Репутация: нет
Всего: 2



Цитата(boostcoder @  27.2.2011,  23:04 Найти цитируемый пост)
с IP - понятно. так: asio::ip::tcp::socket::remote_endpoint().address().to_string()

Мда... увы но не додумался. К сож. справка буста далеко не такого качества как МСДН =) а я привык чтобы все в деталях было. А тут ,как по мне, то оно переводится как удаленная конечная точка, собственно что мне не говорит о том что это сокет =) . Ладно высказал своё "фи", хотя если либы которые намного(!) хуже описаны =) . Хардкор одним словом =))


Цитата(boostcoder @  27.2.2011,  23:04 Найти цитируемый пост)
c TTL - для чего?

ТТЛ это первое что пришло в голову smile . Вообще хотелось бы видеть весь хидер пакета, понимаю что часто этого не надо , но... =) все таки хочется полнсотью контролировать входящий и исходящий трафик smile


Цитата(boostcoder @  27.2.2011,  23:04 Найти цитируемый пост)
boost::bind()

Спасибо большое =). Очень не привычно что тут весь буст связан между собой. Жаль правда что , опять таки, мануал не шибко хорош. Собственно выдержка из доков:

Код

void handler(const boost::system::error_code& error)
{
  if (!error)
  {
    // Timer expired.
  }
}

...

// Construct a timer with an absolute expiry time.
boost::asio::deadline_timer timer(io_service,
    boost::posix_time::time_from_string("2005-12-07 23:59:59.000"));

// Start an asynchronous wait.
timer.async_wait(handler);


Увы там ни слова нету что надо передавать кол-во входящих параметров и конечно же ни слова о том что надо передать еще boost::asio::placeholders::error :( . Ладно, не важно =)) разобрался уже =)). Спасиб большое!

Но думаю вопросов еще будет много  smile . Кстати понял теперь что с помощью boost::bind можно и использовать вэндовские Апи, собственно значит можно сделать свой пул  smile 
PM MAIL   Вверх
Kirgston
Дата 28.2.2011, 14:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 792
Регистрация: 24.12.2007

Репутация: нет
Всего: 2



Опять таки прошу Вашей помощи... как нормально закрыть сессию клиента? о_О

Код

class session
{
public:
    session(boost::asio::io_service& io_service)
        : socket_(io_service), timer(io_service)
    {
        ZeroMemory(data_,max_length);
        InterlockedIncrement(&Connections);
        Terminated = false;
    }

    ~session()
    {
        if (!Terminated)
        {
            InterlockedDecrement(&Connections);
            socket_.shutdown(socket_.shutdown_both);
            socket_.close();
            Terminated = true;
            delete this;
            
        }

    }

    tcp::socket& socket()
    {
        return socket_;
    }

    void start()
    {
        TimeStart();
        socket_.async_read_some(boost::asio::buffer(data_, max_length),
            boost::bind(&session::handle_read, this,
            boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred));
    }

    void handle_read(const boost::system::error_code& error,
        size_t bytes_transferred)
    {
        if (!error)
        {
            std::cout<<data_<<std::endl;
            this->start();
            /*boost::asio::async_write(socket_,
                boost::asio::buffer(data_, bytes_transferred),
                boost::bind(&session::handle_write, this,
                boost::asio::placeholders::error));*/
        }
        else
        {
            this->~session();
        }
    }

    void handle_write(const boost::system::error_code& error)
    {
        if (!error)
        {
            /*socket_.async_read_some(boost::asio::buffer(data_, max_length),
                boost::bind(&session::handle_read, this,
                boost::asio::placeholders::error,
                boost::asio::placeholders::bytes_transferred));    */        
        }
        else
        {
            this->~session();
        }
    }

    void OnTimeOut(const boost::system::error_code& error)
    {
        if (!error)
        {
            if ( strlen(data_) < 1 /*&& Connections > 1*/)
            {
                //std::string str = socket_.remote_endpoint().address().to_string();
                this->~session();
            }
            else
            {
                TimeStart();
            }
        }
        else
        {
            this->~session();
        }
    }

    void TimeStart()
    {
        timer.expires_from_now(boost::posix_time::seconds(5));
        timer.async_wait(boost::bind(&session::OnTimeOut, this, 
            boost::asio::placeholders::error));
    }

private:
    boost::asio::deadline_timer timer;
    tcp::socket socket_;
    enum { max_length = 1024 };
    char data_[max_length];
    bool Terminated;
};


При вызове деструктора я фактически получаю аксес виолешен. Причем деструктор вызывается не 1 раз... :( причем подряд :(
PM MAIL   Вверх
boostcoder
Дата 28.2.2011, 15:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(Kirgston @  28.2.2011,  14:41 Найти цитируемый пост)
деструктор вызывается не 1 раз

естественно smile 
первый:
Цитата(Kirgston @  28.2.2011,  14:41 Найти цитируемый пост)
this->~session();

второй:
Цитата(Kirgston @  28.2.2011,  14:41 Найти цитируемый пост)
delete this;


а что за проблема с закрытием сессии - не понял.
PM WWW   Вверх
Kirgston
Дата 1.3.2011, 23:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 792
Регистрация: 24.12.2007

Репутация: нет
Всего: 2



boostcoder, Собственно на сколько я понял там надо использовать умные указатели. Т.к. можно удалить класс а на самом деле еще внутри ядра буста (а именно асио) висит эвент для него, или нечто похожее. Так что я делал shared_from_this().reset; По крайней мере c delete this точно ничего не вышло

Собственно те старые проблемы решил. Но теперь мой мозг взрывает одна, на первый взгляд, мелочь. Дело в том что сделал таймер для каждой сессии. По истечению таймера идет разрыв связи и удаление класса (ну некий примитивный антифлуд). Оно всё работает (проверяли). Только когда начали проверять на реальном клиенте то оказалось что ничего не работает. А точнее таймер вылетает с ошибкой. Точнее вызывается мой евент для таймера . Ошибка "Операция ввода/вывода была прервана из-за завершения потока команд или по запросу приложения" и код ошибки 995. 

Перед этим идет отправка данных. Но я уже пробовал её убирать - бесполезно. Таймаут вызывается, грубо говоря, в точный промежуток времени. То есть не когда попадая а именно после некоторой ф-ции. Только увы кроме отправки данных (которую я так же убрал) там ничего и нету. 

Вот собственно как у меня таймер настраивается:

Код

    void TimeStart()
    {
        if (!Terminated)
        {
            this->timer.cancel();
            this->timer.expires_from_now(boost::posix_time::seconds(120));
            this->timer.async_wait(boost::bind(&session::OnTimeOut, shared_from_this(), 
                boost::asio::placeholders::error));
        }
    }


Собственно данная ф-ция вызывается всякий раз когда пришел пакет. Хотя у меня и не так много пакетов приходит... всего 3 =)

Может проблема в указателях ... поэтому выкладываю еще и метод управления с помощью них:
Главная часть:
Код

class server
{
public:
    server(boost::asio::io_service& io_service, short port)
        : io_service_(io_service),
        acceptor_(io_service, tcp::endpoint(tcp::v4(), port)), timer(io_service)
    {
        this->port = port;
        session::pointer new_session = session::create(io_service_);

        acceptor_.async_accept(new_session->socket(),
            boost::bind(&server::handle_accept, this, new_session,
            boost::asio::placeholders::error));
    }

    void handle_accept(session::pointer new_session,
        const boost::system::error_code& error)
    {
        if (!error)
        {
                new_session->start();
                new_session = new session(io_service_);
                new_session = session::create(io_service_);
                acceptor_.async_accept(new_session->socket(),
                    boost::bind(&server::handle_accept, this, new_session,
                    boost::asio::placeholders::error));
        }
        else
        {
            new_session->shared_from_this().reset();
        }
    }


private:
    boost::asio::ip::tcp::endpoint accepting_endpoint;        
    boost::asio::deadline_timer timer;
    boost::asio::io_service& io_service_;
    tcp::acceptor acceptor_;
    int port;
};

Кусочек сесии: (там много лишнего поетому всё и не выкладывал)
Код

class session : public boost::enable_shared_from_this<session> 
{
public:
    //-----------
    typedef boost::shared_ptr<session> pointer;
    //-----------

    //---------------------------------------------------------------------------

    static pointer create(boost::asio::io_service& io_service) 
    {
        return pointer(new session(io_service));
    }

    //---------------------------------------------------------------------------

    session(boost::asio::io_service& io_service)
        : socket_(io_service), timer(io_service)
    {
        Num = Connections;
        InterlockedIncrement(&Connections);
        Terminated = false;
        SendBytes = 0;
    }

    void start()
    {
        if (!Terminated)
        {
            this->SCConnectResultSend(0x01);
            strcpy(m_Ip,socket_.remote_endpoint().address().to_string().c_str());
            this->TimeStart();
            this->socket_.async_receive(boost::asio::buffer(data_, max_length),
                boost::bind(&session::handle_read, shared_from_this(),
                boost::asio::placeholders::error,
                boost::asio::placeholders::bytes_transferred));
        }
    }



Все указатели у меня в виде shared_from_this() . Может их не правильно сделал?
PM MAIL   Вверх
boostcoder
Дата 2.3.2011, 00:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(Kirgston @  1.3.2011,  23:45 Найти цитируемый пост)
сделал таймер для каждой сессии.

во первых - это не рационально. обычно подобное реализуется при помощи единственного контейнера состояний, каждый элемент которого, содержит, помимо прочего, переменную содержащую время последней активности. я для этого использую time_t, полученный от time().
так вот... раз в 10 секунд(такой у меня таймаут для определения что клиент тупит/висит), проверяем все временные метки, и ту, которая превысила таймаут - удаляем.
этой задачей у меня занимается класс sheduler, который помимо описанного, еще и занимается рассылкой новостей, обновлением статистики в клиентской программе, банера, чата, и всякой ерундой.

Цитата(Kirgston @  1.3.2011,  23:45 Найти цитируемый пост)
 А точнее таймер вылетает с ошибкой. Точнее вызывается мой евент для таймера .

это, пожалуйста еще раз, без эмоций ;)


зы
код сейчас гляну...

Добавлено @ 00:02
Цитата(Kirgston @  1.3.2011,  23:45 Найти цитируемый пост)
void TimeStart()

член какого класса?

Добавлено @ 00:04
Цитата(Kirgston @  1.3.2011,  23:45 Найти цитируемый пост)
new_session = new session(io_service_);
                new_session = session::create(io_service_);

тут дважды создаете объект сессии.
используйте второй способ ;)

Добавлено через 6 минут и 49 секунд
в хэндлерах, в else-блоках, сделайте вывод в консоль, или в лог.

в остальном ничего критичного не заметил.

Добавлено через 8 минут и 57 секунд
из конструктора и деструктора объекта сессии, тоже сделайте вывод. это позволит видеть моменты создания и удаления сессий.

Добавлено через 10 минут и 28 секунд
Цитата(Kirgston @  1.3.2011,  23:45 Найти цитируемый пост)
Все указатели у меня в виде shared_from_this()

в данной модели сессии, так и должно быть.

Добавлено через 12 минут и 10 секунд
Цитата(Kirgston @  1.3.2011,  23:45 Найти цитируемый пост)
session(boost::asio::io_service& io_service)

в примере, конструктор сессии был приватным, если не ошибаюсь. это для того, чтоб объекты сессии создавались только при помощи ее статической функции create()

Это сообщение отредактировал(а) boostcoder - 2.3.2011, 00:04
PM WWW   Вверх
Kirgston
Дата 2.3.2011, 00:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 792
Регистрация: 24.12.2007

Репутация: нет
Всего: 2



Цитата(boostcoder @  2.3.2011,  00:01 Найти цитируемый пост)
во первых - это не рационально. обычно подобное реализуется при помощи единственного контейнера состояний, каждый элемент которого, содержит, помимо прочего, переменную содержащую время последней активности. я для этого использую time_t, полученный от time().

совершенно согласен. Но как тогда? Создавать тот же вектор или список с указателями на классы и скажем раз в 10 секунд пробегаться по всем существующим классам?


Цитата(boostcoder @  2.3.2011,  00:01 Найти цитируемый пост)
это, пожалуйста еще раз, без эмоций ;)

Просто вызывается OnTimeOut
Код

void OnTimeOut(const boost::system::error_code& error)

в котором error != NULL, а собственно и произошла где то ошибка. Почему? знать не знаю :(. Собственно код ошибки приводил выше.


Цитата(boostcoder @  2.3.2011,  00:01 Найти цитируемый пост)
член какого класса?

session


Цитата(boostcoder @  2.3.2011,  00:01 Найти цитируемый пост)
тут дважды создаете объект сессии.используйте второй способ ;)

опс... банальная очепятка. Второй и используется. Первый закоментирован

П.С. добавил файлик который отвечает за обработку. Собственно в нем все и проблемы. Буду очень признателен если посмотрите! 

Это сообщение отредактировал(а) Kirgston - 3.3.2011, 08:40
PM MAIL   Вверх
boostcoder
Дата 2.3.2011, 00:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(Kirgston @  2.3.2011,  00:17 Найти цитируемый пост)
Но как тогда? Создавать тот же вектор или список с указателями на классы и скажем раз в 10 секунд пробегаться по всем существующим классам?

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

Цитата(Kirgston @  2.3.2011,  00:17 Найти цитируемый пост)
error != NULL

никогда не сравнивал boost::system::error_code с NULL. но подозреваю, что происходит сравнение с нулем.
достаточно просто if ( error ) { значит есть ошибка }

Цитата(Kirgston @  2.3.2011,  00:17 Найти цитируемый пост)
Буду очень признателен если посмотрите!  

посмотрю.

Добавлено через 2 минуты и 27 секунд
Цитата(Kirgston @  2.3.2011,  00:17 Найти цитируемый пост)
 добавил файлик который отвечает за обработку

в начале файла есть такое:
Код

using boost::asio::ip::tcp;
boost::asio::io_service io_service;


long    Connections = 0;
long    ConnectCount = 0;
long    DisConnectCount = 0;
int        g_ServerPort;
HANDLE    g_IocpThreadHandle;
wchar_t    ErrorMsg[512];
bool    CSEnabled;

void ServerWorkerTh();
int CreateGIocp(int server_port);
void DestroyGIocp();


скажите, в реальном коде все так же?

Добавлено через 8 минут и 30 секунд
в session, убери все строчки: shared_from_this().reset();
рекомендую почитать: http://www.boost.org/doc/libs/1_46_0/libs/..._from_this.html и задуматься над смыслом применения reset() к результату shared_from_this()

Добавлено через 10 минут и 26 секунд
Цитата

    this->Stop();

не нужно такого делать. почитайте все же приведенную мною ссылку.
PM WWW   Вверх
boostcoder
Дата 2.3.2011, 00:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



есть такой метод:
Код

    void AsyncWrite(unsigned char* data,int len)
    {
        this->socket_.async_send(boost::asio::buffer(data, len),
            boost::bind(&session::handle_write, shared_from_this(),
            boost::asio::placeholders::error));
    }


далее его вызов таким образом:
Код

    void SCConnectResultSend(BYTE result)
    {
        PMSG_CONNECTRESULT    pMsg;

        pMsg.h.c        = PMHC_BYTE;
        pMsg.h.headcode = 0x00;
        pMsg.h.size        = sizeof(pMsg);
        pMsg.result        = result;

        this->AsyncWrite((LPBYTE)&pMsg,pMsg.h.size);
    }


угадайте, на что указывает аргумент AsyncWrite() после выхода из SCConnectResultSend() ? ;)
далее, еще 6 раз повторяется та же ошибка.

в общем, проще переписать с нуля.

Добавлено через 2 минуты и 56 секунд
не забываем про спасибо ;)

Это сообщение отредактировал(а) boostcoder - 2.3.2011, 00:40
PM WWW   Вверх
Kirgston
Дата 2.3.2011, 08:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 792
Регистрация: 24.12.2007

Репутация: нет
Всего: 2



Цитата(boostcoder @  2.3.2011,  00:23 Найти цитируемый пост)
скажите, в реальном коде все так же?

Да, подозреваю что сейчас меня закидают тухлыми яйцами и помидорами  smile . Ведь в идеале это всё надо поместить в класс с класса уже всё это делать 

Цитата(boostcoder @  2.3.2011,  00:23 Найти цитируемый пост)
в session, убери все строчки: shared_from_this().reset();рекомендую почитать: http://www.boost.org/doc/libs/1_46_0/libs/..._from_this.html и задуматься над смыслом применения reset() к результату shared_from_this()

По сути shared_from_this() это и есть *this , если конечно я правильно понял. Просто в одном, уже, горе примере видел такое:

Код

// reset pointer to themself, destroying current object
        shared_from_this().reset();


Собственно линк: http://alexott.net/common/asio-notes/test-otpc-conn.cpp.html

Вот я и... smile А как тогда удалять объекты? Сомневаюсь что просто надо delete this ведь колбеки есть то... а они могут вернутся уже после(!) (что собственно уже было проверено) вызова this. 


Цитата(boostcoder @  2.3.2011,  00:23 Найти цитируемый пост)
не нужно такого делать. почитайте все же приведенную мною ссылку.

Читал... просто буст достаточно велик и не всё сразу понимаю =)), тогда так? shared_from_this()->Stop(); . Тогда что, все вызовы с этого же класса (this) переделать в shared_from_this() ?


Цитата(boostcoder @  2.3.2011,  00:38 Найти цитируемый пост)
угадайте, на что указывает аргумент AsyncWrite() после выхода из SCConnectResultSend() ? ;)


Честно , хоть убейте не понимаю...
Код

typedef BYTE far            *LPBYTE;
typedef unsigned char       BYTE;

this->AsyncWrite((LPBYTE)&pMsg,pMsg.h.size);


Собственно мы же сначала берем адрес а потом ставим на этот адрес указатель на unsigned char. Вроде всё законно . Да и размер нормально передается. Или опять таки shared_from_this()->AsyncWrite ? Хотя не шибко понимаю... ведь shared_from_this() указывает на this... или я не прав?


Цитата(boostcoder @  2.3.2011,  00:38 Найти цитируемый пост)
в общем, проще переписать с нуля.

Может, но для начала лучше понять как правильно писать  smile 
PM MAIL   Вверх
boostcoder
Дата 2.3.2011, 09:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(Kirgston @  2.3.2011,  08:56 Найти цитируемый пост)
Да, подозреваю что сейчас меня закидают тухлыми яйцами и помидорами. Ведь в идеале это всё надо поместить в класс с класса уже всё это делать

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

Цитата(Kirgston @  2.3.2011,  08:56 Найти цитируемый пост)
По сути shared_from_this() это и есть *this , если конечно я правильно понял. Просто в одном, уже, горе примере видел такое:
код C++
// reset pointer to themself, destroying current object
        shared_from_this().reset();


Собственно линк: http://alexott.net/common/asio-notes/test-otpc-conn.cpp.html

Вот я и...  А как тогда удалять объекты? Сомневаюсь что просто надо delete this ведь колбеки есть то... а они могут вернутся уже после(!) (что собственно уже было проверено) вызова this. 


Цитата(boostcoder @  2.3.2011,  00:23 )
не нужно такого делать. почитайте все же приведенную мною ссылку.

Читал... просто буст достаточно велик и не всё сразу понимаю =)), тогда так? shared_from_this()->Stop(); . Тогда что, все вызовы с этого же класса (this) переделать в shared_from_this() ?

про бложек уже писал ;)

shared_from_this() создает новый смарт-поинтер на this, тем самым инкрементируя счетчик ссылок. применяя к результату вызова shared_from_this(), reset() - происходит декрементирование. т.е. смысла в этом выражении ноль!

Цитата(Kirgston @  2.3.2011,  08:56 Найти цитируемый пост)
Собственно мы же сначала берем адрес а потом ставим на этот адрес указатель на unsigned char. Вроде всё законно . Да и размер нормально передается. Или опять таки shared_from_this()->AsyncWrite ? Хотя не шибко понимаю... ведь shared_from_this() указывает на this... или я не прав?

после выхода из SCConnectResultSend(), указатель, указывает в никуда ;)
size - да, содержит правильный размер только потому, что он передается по значению.

в общем решается это так:
Код

    void AsyncWrite(boost::shared_ptr<PMSG_CONNECTRESULT> data)
    {
        this->socket_.async_send(boost::asio::buffer(data, data->h.size),
            boost::bind(&session::handle_write, shared_from_this(),
            data,
            boost::asio::placeholders::error));
    }
    
    void handle_write(boost::shared_ptr<PMSG_CONNECTRESULT>, const boost::system::error_code& e) {
        ....
    }

    void SCConnectResultSend(BYTE result)
    {
        boost::shared_ptr<PMSG_CONNECTRESULT> pMsg(new PMSG_CONNECTRESULT);
        pMsg.h.c        = PMHC_BYTE;
        pMsg.h.headcode = 0x00;
        pMsg.h.size        = sizeof(pMsg);
        pMsg.result        = result;
        this->AsyncWrite(pMsg);
    }


Добавлено через 13 минут и 45 секунд
Up.

Это сообщение отредактировал(а) boostcoder - 2.3.2011, 09:32
PM WWW   Вверх
Kirgston
Дата 2.3.2011, 09:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 792
Регистрация: 24.12.2007

Репутация: нет
Всего: 2



Цитата(boostcoder @  2.3.2011,  09:18 Найти цитируемый пост)
shared_from_this() создает новый смарт-поинтер на this, тем самым инкрементируя счетчик ссылок. применяя к результату вызова shared_from_this(), reset() - происходит декрементирование. т.е. смысла в этом выражении ноль!


А как тогда удалить класс ? =))) вручную останавливать все коллбеки , закрывать всё всё всё и потом delete this? O_o


Цитата(boostcoder @  2.3.2011,  09:18 Найти цитируемый пост)
после выхода из SCConnectResultSend(), указатель, указывает в никуда ;)size - да, содержит правильный размер только потому, что он передается по значению.

Ну... и да и нет =). Почему? Говорю только то что вижу =). Собственно когда вызывается this->AsyncWrite(pMsg); деструктор, грубо говоря, функции еще не вызван. И те объекты еще живут. Насколько я понимаю (конечно я могу и заблуждаться). Данные объекты не видны за пределами этой ф-ции. Но ведь где то в памяти для них выделено место, верно? И если есть права записи\чтения из этой области то я думаю что спокойно можно поставить указатель. Конечно, если поставить брейкпоинт на AsyncWrite то в data будет только первый символ. Но я предполагаю что там так же идет нечто типа memcpy(buf,(void*)&data,len); или что то такое. Т.к. я проходился сниффером пакетов и там четко видно что все пакеты приходят именно "как надо" =). То есть полностью. Значит внутри всё норм?

Правда для теста сейчас вообще удалю AsyncWrite и забабахаю отправку в каждой ф-ции. Быдлокод конечно... но что поделать? надо же понять почему таймер так начинает сбоить... (хотя если честно то у меня и на одном коннекте он сбоит... )
PM MAIL   Вверх
boostcoder
Дата 2.3.2011, 09:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(Kirgston @  2.3.2011,  09:35 Найти цитируемый пост)
А как тогда удалить класс ? =))) вручную останавливать все коллбеки , закрывать всё всё всё и потом delete this?

объект сам удалится ;)


Цитата(Kirgston @  2.3.2011,  09:35 Найти цитируемый пост)
Собственно когда вызывается this->AsyncWrite(pMsg); деструктор, грубо говоря, функции еще не вызван. И те объекты еще живут. Насколько я понимаю (конечно я могу и заблуждаться).

когда вызываешь - да. но когда выходишь из SCConnectResultSend(), на что они указывают? ;)
а так как ты вызываешь асинхронную операцию, она вернет управление сразу, а реальная запись данных произойдет несколько позже. потому в доке и говорится:
Цитата

When you call an asynchronous read or write you need to ensure that the buffers for the operation are valid until the completion handler is called.


Цитата(Kirgston @  2.3.2011,  09:35 Найти цитируемый пост)
Но ведь где то в памяти для них выделено место, верно?

нет. данные находятся на стеке, и валидны до выхода из блока.

Цитата(Kirgston @  2.3.2011,  09:35 Найти цитируемый пост)
И если есть права записи\чтения из этой области то я думаю что спокойно можно поставить указатель. Конечно, если поставить брейкпоинт на AsyncWrite то в data будет только первый символ. Но я предполагаю что там так же идет нечто типа memcpy(buf,(void*)&data,len); или что то такое. Т.к. я проходился сниффером пакетов и там четко видно что все пакеты приходят именно "как надо" =). То есть полностью. Значит внутри всё норм?

Правда для теста сейчас вообще удалю AsyncWrite и забабахаю отправку в каждой ф-ции. Быдлокод конечно... но что поделать? надо же понять почему таймер так начинает сбоить... (хотя если честно то у меня и на одном коннекте он сбоит... ) 

бессмысленное занятие, правда.

Добавлено через 3 минуты и 23 секунды
вот конкретный пример из доки:
Код

void dont_do_this()
{
 std::string msg = "Hello, world!";
 boost::asio::async_write(sock, boost::asio::buffer(msg), my_handler);
}

даже название функции соответствующее ;)

Это сообщение отредактировал(а) boostcoder - 2.3.2011, 09:45
PM WWW   Вверх
Kirgston
Дата 2.3.2011, 10:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 792
Регистрация: 24.12.2007

Репутация: нет
Всего: 2



Цитата(boostcoder @  2.3.2011,  09:43 Найти цитируемый пост)
объект сам удалится ;)

Хм.. тогда надо вызвать socket_.shutdown + socket_.close? Или просто socket_.shutdown ? 

Кстати... вот эти умные указатели... они же наверно кучу ресурсов жрут? =)


Цитата(boostcoder @  2.3.2011,  09:43 Найти цитируемый пост)
когда вызываешь - да. но когда выходишь из SCConnectResultSend(), на что они указывают? ;)а так как ты вызываешь асинхронную операцию, она вернет управление сразу, а реальная запись данных произойдет несколько позже. потому в доке и говорится:

Да, что то не подумал... увы


Цитата(boostcoder @  2.3.2011,  09:43 Найти цитируемый пост)
бессмысленное занятие, правда.


Собственно создал шаблон, но мучают сомнения что он опять крив
Код

    template<typename T> void AsyncWrite(boost::shared_ptr<T> data, int len)
    {
        socket_.async_send(boost::asio::buffer((LPBYTE)&data, len),
            boost::bind(&session::handle_write, shared_from_this(),
            boost::asio::placeholders::error));
    }


 т.к. опять таки указатель на память... но как иначе? Мне ведь надо как то структуру переделать в набор данных. Или еще до вызова AsyncWrite переделать в UCHAR и повесить умный указатель?


Цитата(boostcoder @  2.3.2011,  09:43 Найти цитируемый пост)
вот конкретный пример из доки:код C++1:2:3:4:5:void dont_do_this(){ std::string msg = "Hello, world!"; boost::asio::async_write(sock, boost::asio::buffer(msg), my_handler);}highlightSyntax('cpp_I0OGYx','cpp');даже название функции соответствующее ;)


Не увидел  smile 


Очень извиняюсь, просто уже путаться начал  smile 
PM MAIL   Вверх
boostcoder
Дата 2.3.2011, 10:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(Kirgston @  2.3.2011,  10:35 Найти цитируемый пост)
Хм.. тогда надо вызвать socket_.shutdown + socket_.close? Или просто socket_.shutdown ?

при разрушении объекта сессии, сокет закроется в любом случае, потому что он является членом сессии.

Цитата(Kirgston @  2.3.2011,  10:35 Найти цитируемый пост)
умные указатели... они же наверно кучу ресурсов жрут?

не то чтобы много...но жрут.

Цитата(Kirgston @  2.3.2011,  10:35 Найти цитируемый пост)
Собственно создал шаблон

смарт-поинтер передаваемый в шаблон, передай его дальше в хэндлер.

это:
Цитата(Kirgston @  2.3.2011,  10:35 Найти цитируемый пост)
boost::asio::buffer((LPBYTE)&data, len)

так:
Код

boost::asio::buffer(data.get(), len)


Цитата(Kirgston @  2.3.2011,  10:35 Найти цитируемый пост)
Мне ведь надо как то структуру переделать в набор данных.

правильно, это делается при помощи сериализации ;)
PM WWW   Вверх
Kirgston
Дата 2.3.2011, 14:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 792
Регистрация: 24.12.2007

Репутация: нет
Всего: 2



Цитата(boostcoder @  2.3.2011,  10:42 Найти цитируемый пост)
при разрушении объекта сессии, сокет закроется в любом случае, потому что он является членом сессии.

Само собой. Но если напрямую нельзя вызвать delete this из-за возможных побочных эффектов, тогда как?  smile 


Цитата(boostcoder @  2.3.2011,  10:42 Найти цитируемый пост)
правильно, это делается при помощи сериализации ;)

Ага, с этим уже раз работал =) правда я так юникод передавал =)) чтобы не заморачиватся с разбиением и переделываем юникода в массив тех же UCHAR использовал сериализацию. Кстати тогда Вы тоже помогли с примером  smile . Правда именно в моем случае тут делать так низя. Ибо клиент на такое не рассчитан. Сурса от клиента увы нет, хотя... в принципе можно поставить хуки на те же WSA(Send\Recv) & recv\send и дописать туда сериализацию сразу и защита будет  smile

Добавлено через 14 минут и 20 секунд
По сути на счет дисконнекта и разрушения объекта я имею такие предположения:

1) delete this . Но кажется что это чревато. Класс удалится, но в ядре асио может остаться коллбек или что то такое на выделенную область памяти под класс. В итоге акксес виолейшен
2) socket_.close \ socket_.shutdown . Я не знаю как работает асио внутри... но при дисконекте вызванном самим клиентом то автоматически разрушается и класс. Вот собственно и появилась мысля... что если разорвать связь то автоматически и закроется класс  smile 
3) shared_from_this().reset . Вроде оно освобождало... ну по крайней мере рамка прыгала с 8мб до 5 и обратно =). Хотя могу ошибаться...


Собственно вот такие вот мысли ... а что из этого верно? =) извините за тупость, просто пока только учусь и множество вещей понимаю именно с видимого результата и чисто своих предположений
PM MAIL   Вверх
Страницы: (3) Все 1 [2] 3 
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Сети | Следующая тема »


 




[ Время генерации скрипта: 0.0708 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.