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

Поиск:

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


Опытный
**


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

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



Всем доброго времени суток! Собственно изучаю данный сабж и пытаюсь написать сервер какой должен отвечать на запросы и всё такое. Сервер будет работать не(!) с клиентами написаными на asio , хотя что то мне подсказывает что разницы быть не должно. Но у меня появилась проблема... коннекты сервер принимает , а вот с обменом сообщений - туго.  Для теста использовал ранее написаную утилиту которая просто отправляет и читает пакет в ответ. Суть в том что коннект происходит нормально, и моя утилита сразу же отправляет сообщение и ждет другое сообщение в ответ. Но сервер (на бусте) вообще не вызывает handle_read , а точнее вызывает только когда утилита по таймауту дисконектится . Вот и не понимаю что у меня не так...

Код

#include "common.h"
#include <deque>

typedef std::deque<io_service_ptr> ios_deque;

//Класс для асинхронного ввода\вывода

class connection : public boost::enable_shared_from_this<connection> 
{
public:
    typedef boost::shared_ptr<connection> pointer;

    //создаем новое соеденение
    static pointer create(ba::io_service& io_service) 
    {
        return pointer(new connection(io_service));
    }

    //возвращаем сокет созданого соеденения (используется для приятия соеденений)
    ba::ip::tcp::socket& socket() 
    {
        return socket_;
    }


    void start() 
    {
        // начинаем считывать сообщения пока не получим "\r\n\r\n"
        boost::asio::async_read_until(socket_, buf, boost::regex("\r"), boost::bind(&connection::handle_read, shared_from_this(), ba::placeholders::error, ba::placeholders::bytes_transferred));
    }

private:

    //инициализация подключения
    connection(ba::io_service& io_service) : socket_(io_service) 
    {

    }

    //вызывается когда с данного сервиса идет запись 
    void handle_write(const boost::system::error_code& error, size_t bytes_transferred) 
    {

    }
    
    //вызывается перед тем как будет прочитано сообщение от клиента
    void handle_read(const boost::system::error_code& error, size_t bytes_transferred) 
    {
        ba::async_write(socket_, 
                            ba::buffer(message_),
                                boost::bind(&connection::handle_write, shared_from_this(),
                                            ba::placeholders::error,
                                                ba::placeholders::bytes_transferred));
    }
    
    ba::ip::tcp::socket socket_; //сокет с которым асоциируется сервсис
    boost::asio::streambuf buf;  //буфер для данных
    static std::string message_; //буфер для сообщения на отправку
    std::string connection::message2_;
};

std::string connection::message_="hello";





class server 
{
public:

    server(const ios_deque& io_services, int port = 5500) : io_services_(io_services), acceptor_(*io_services.front(), ba::ip::tcp::endpoint(ba::ip::tcp::v4(), port) ) 
    {
        start_accept();
    }

private:

    void start_accept() 
    {
        // выбираем следующий io_service
        io_services_.push_back(io_services_.front());
        io_services_.pop_front();
        // создаем новый коннект
        connection::pointer new_connection = connection::create(*io_services_.front());
        // запускаем прием данных в асинхронном р-ме
        acceptor_.async_accept(new_connection->socket(), boost::bind(&server::handle_accept, this, new_connection, ba::placeholders::error) );//начинаем асинхронный прием
    }

    void handle_accept(connection::pointer new_connection, const boost::system::error_code& error)  
    {
        if (!error)//если произошла ошибка это будет значить то что данный сервис уже принимает
        {//иначе запускаем этот сервис и переходим к следующему
            new_connection->start();
            start_accept();
        }
    }

    ios_deque io_services_;          //список указателей на  io_services
    ba::ip::tcp::acceptor acceptor_; //класс отвечающий за новые подключения 
};


int main() {
    try {
        SYSTEM_INFO SystemInfo;
        GetSystemInfo(&SystemInfo);
        int thread_num = SystemInfo.dwNumberOfProcessors * 2;//устанавливаем кол-во нитей

        ios_deque io_services;//очередь из сервисом которые будут производить чтение\запись (аля 1 очередь - 1 поток)
        std::deque<ba::io_service::work> io_service_work;//класс для информирования io сервиса о окончании работы с нитями
        
        boost::thread_group thr_grp;//контейнер для обеденения потоков в групы
        // создаем каждому io_service по нити
        for (int i = 0; i < thread_num; ++i) {
            io_service_ptr ios(new ba::io_service);//просто создаем новый сервис
            io_services.push_back(ios);//и помещаем его в контейнер
            io_service_work.push_back(ba::io_service::work(*ios));//передаем этот сервис в класс для информирования 
            
            thr_grp.create_thread(boost::bind(&ba::io_service::run, ios));//запускаем каждый сервис в своем потоке
        }
        // запускаем сам сервер обработки сообщений
        server server(io_services);
        // и просто начинаем ждать пока все потоки не завершат свою работу
        thr_grp.join_all();
    } catch (std::exception& e) {
        std::cerr << e.what() << std::endl;//если что то произошло то вызываем бустовский ексепшен
    }


    return 0;
}


     
Благодарю всех и каждого в помощи изучения этого не простого дела!  smile 

PM MAIL   Вверх
Kirgston
Дата 26.2.2011, 18:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



На сколько я понимаю проблема в async_read_until. Подставлял просто "\r\n" но ничего не менялось. Не понимаю почему "оно" не видит конца пакета
PM MAIL   Вверх
boostcoder
Дата 27.2.2011, 02:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


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

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



Цитата(Kirgston @  26.2.2011,  18:37 Найти цитируемый пост)
Не понимаю почему "оно" не видит конца пакета 

а он(конец пакета) есть?
если есть сложность с просмотром пакетов, то рекомендую почитать это: http://www.boost.org/doc/libs/1_46_0/doc/h.../overload4.html

Добавлено через 2 минуты и 33 секунды
Цитата(Kirgston @  26.2.2011,  09:24 Найти цитируемый пост)
ios_deque io_services_;          //список указателей на  io_services

нет ни малейшей надобности в нескольких io_service`ах. в вашем случае точно нет.
PM WWW   Вверх
Kirgston
Дата 27.2.2011, 09:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(boostcoder @  27.2.2011,  02:30 Найти цитируемый пост)
а он(конец пакета) есть?

да =). я уже в ручную дописывал, и использовал в качестве утилиты билдер (который сам , при использовании Инди, дописывает \r\n в конец)


Цитата(boostcoder @  27.2.2011,  02:30 Найти цитируемый пост)
нет ни малейшей надобности в нескольких io_service`ах. в вашем случае точно нет.

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

Имеется ввиду что... например создается 4 потока которые ждут пакет. Например , приходит 4 пакета от разных (!) клиентов. Вот тут я могу и ошибатся , но вот мое предположение: если 1 нить то пакеты будут обрабатыватся постепенно. То есть сначала первый потом второй а потом третий. Если же 4 нити то все пакеты будут обработаны за один приход. Я заблуждаюсь или нет? =)
PM MAIL   Вверх
boostcoder
Дата 27.2.2011, 10:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


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

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



Цитата(Kirgston @  27.2.2011,  09:49 Найти цитируемый пост)
Но в конце ,у меня задача, должен быть быстрый и масштабируемый сервер который будет быстро обрабатывать клиентов.

в одном из своих проектов, я, при использовании одного io_service`а и пула потоков, достиг ~178000 запросов-ответов от 6800 юзеров онлайн, в секунду ;)
это как пример того, что кол-во io_service`ов ни коим образом не влияет на производительность. я бы даже сказал наоборот.

Цитата(Kirgston @  27.2.2011,  09:49 Найти цитируемый пост)
я уже в ручную дописывал

пошли два пакета подряд. ради теста.

и еще, перейди по ссылке и почитай. такой способ очень удобен для отладки.

Добавлено @ 10:52
Цитата(Kirgston @  27.2.2011,  09:49 Найти цитируемый пост)
если 1 нить то пакеты будут обрабатыватся постепенно. То есть сначала первый потом второй а потом третий. Если же 4 нити то все пакеты будут обработаны за один приход. Я заблуждаюсь или нет?

в этом ты прав. но это не значит что кол-во io_service`ов или рабочих потоков должно равняться кол-ву одновременно пришедших пакетов.

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


Опытный
**


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

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



Цитата(boostcoder @  27.2.2011,  10:50 Найти цитируемый пост)
в одном из своих проектов, я, при использовании одного io_service`а и пула потоков, достиг ~178000 запросов-ответов от 6800 юзеров онлайн ;)это как пример того, что кол-во io_service`ов ни коим образом не влияет на производительность. я бы даже сказал наоборот.

впечатляет конечно =) , вот именно , примерно, такое мне и надо smile . Только тогда у меня еще один вопросец... threadpool уже не в бусте (автор , как понимаю, закинул проект). Реализовать пул можно и самому с тем же WinApi. Но может быть есть какие-то платформонезависимые решения?

 
Цитата(boostcoder @  27.2.2011,  10:50 Найти цитируемый пост)
пошли два пакета подряд. ради теста.

Пробовал, нивкакую =). Есть большое подозрение... дело в том что у меня например создается 4 нити в которых идет обработка сообщения. Так вот... что то мне подсказывает что там просто дезлок. То есть при коннекте считывание разрешается только одной нити. Вот мне и кажется что когда идет коннект то одна нить переходит в работу с клиентом, а другая хочет считывать дальше сообщения. Вот и получается дезлок.


PM MAIL   Вверх
boostcoder
Дата 27.2.2011, 11:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


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

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



Цитата(Kirgston @  27.2.2011,  10:59 Найти цитируемый пост)
threadpool уже не в бусте

это: http://www.boost.org/doc/libs/1_46_0/doc/h...ent.threadgroup
конечно, это не пул, а просто группа потоков. но для большинства задач подходит.

Цитата(Kirgston @  27.2.2011,  10:59 Найти цитируемый пост)
дело в том что у меня например создается 4 нити в которых идет обработка сообщения. Так вот... что то мне подсказывает что там просто дезлок. То есть при коннекте считывание разрешается только одной нити. Вот мне и кажется что когда идет коннект то одна нить переходит в работу с клиентом, а другая хочет считывать дальше сообщения. Вот и получается дезлок.

не понял.
PM WWW   Вверх
Kirgston
Дата 27.2.2011, 12:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(boostcoder @  27.2.2011,  11:24 Найти цитируемый пост)
это: http://www.boost.org/doc/libs/1_46_0/doc/h...ent.threadgroupконечно, это не пул, а просто группа потоков. но для большинства задач подходит.

хмм... почитал... но если я не ошибаюсь это просто обертка над потоками? И по сути там нету ни задания для потоков на установку в очередь пула для обработки некой ф-ции, ни автоматического расширения кол-ва потоков и автоматического анализа сколько надо создать тредов. По сути это всё на плечи программиста . И выходит что если без танцов с бубном то 1 клиент = 1 нить, верно? Или я чего то не допонимаю? smile
PM MAIL   Вверх
boostcoder
Дата 27.2.2011, 16:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


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

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



Цитата(Kirgston @  27.2.2011,  12:26 Найти цитируемый пост)
по сути там нету ни задания для потоков на установку в очередь

http://www.boost.org/doc/libs/1_46_0/doc/h...p.create_thread

Цитата(Kirgston @  27.2.2011,  12:26 Найти цитируемый пост)
ни автоматического расширения кол-ва потоков и автоматического анализа сколько надо создать тредов

да, этого нет.

Цитата(Kirgston @  27.2.2011,  12:26 Найти цитируемый пост)
По сути это всё на плечи программиста

угу.
но вы торопите события. об этом можно думать тогда, когда проект написан и работает.

Цитата(Kirgston @  27.2.2011,  12:26 Найти цитируемый пост)
выходит что если без танцов с бубном то 1 клиент = 1 нить, верно?

не верно.
читайте: http://forum.vingrad.ru/index.php?showtopi...t&p=2306244
PM WWW   Вверх
Kirgston
Дата 27.2.2011, 22:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(boostcoder @  27.2.2011,  16:57 Найти цитируемый пост)
http://www.boost.org/doc/libs/1_46_0/doc/h...p.create_thread


Цитата(boostcoder @  27.2.2011,  16:57 Найти цитируемый пост)
не верно.читайте: http://forum.vingrad.ru/index.php?showtopi...t&p=2306244


спасибо =) с пулами будем разбиратся


Цитата(boostcoder @  27.2.2011,  16:57 Найти цитируемый пост)
об этом можно думать тогда, когда проект написан и работает.

Начал делать по Вашему совету... но в ходе процесса появилось множество вопросов(увы но мануал еще больше завел в тупик) 
1) почему не работает данный код:
Код

class session
{
public:
  session(boost::asio::io_service& io_service)
    : socket_(io_service), timer(io_service)
  {

  }


  void OnTimeOut(const boost::system::error_code& error)
  {
    if (!error)
    {
      if ( strlen(data_) < 1)
      {
        socket_.shutdown(socket_.shutdown_both);
        socket_.close();
        delete this;
      }
      else
      {
        TimeStart();
      }
    }
  }

  void TimeStart()
  {
    timer.expires_from_now(boost::posix_time::seconds(5));
    timer.async_wait(OnTimeOut);
  }

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



Писал по примеру из http://www.boost.org/doc/libs/1_39_0/doc/h...line_timer.html . Вся разница в классе, не более. Ошибка на стадии компиляции: 
">c:\users\алекс\documents\visual studio 2010\projects\asioserver2\asioserver2\main.cpp(93): error C3867: session::OnTimeOut: в вызове функции отсутствует список аргументов; используйте "&session::OnTimeOut" для создания указателя на член"

По сути мне просто надо сделать таймер в котором буду проверять пришел ли ответ от клиента или же он "уснул" . И если уснул то надо закрыть связь.

2) как можно настроить max_connections? Ибо это увы, константа :( Или для решения вопроса о максимально допустимом числе одновременных коннектов надо писать свой счетчик? smile

3) как можно узнать тот же IP, TTL и все прочие прелести от входного коннекта? Т.к. , вроде, в tcp::socket ничего интересного не нашел.

Благодарю !  smile 
PM MAIL   Вверх
boostcoder
Дата 27.2.2011, 22:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


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

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



Цитата(Kirgston @  27.2.2011,  22:18 Найти цитируемый пост)
 session::OnTimeOut: в вызове функции отсутствует список аргументов; используйте "&session::OnTimeOut" для создания указателя на член"

потому что не совпадают ожидаемая сигнатура, и предоставленная вами.

Цитата(Kirgston @  27.2.2011,  22:18 Найти цитируемый пост)
Или для решения вопроса о максимально допустимом числе одновременных коннектов надо писать свой счетчик?

угу

Цитата(Kirgston @  27.2.2011,  22:18 Найти цитируемый пост)
как можно узнать тот же IP, TTL и все прочие прелести от входного коннекта?

откуда такая надобность? Оо
PM WWW   Вверх
Kirgston
Дата 27.2.2011, 22:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(boostcoder @  27.2.2011,  22:51 Найти цитируемый пост)
откуда такая надобность? Оо

Очень простой пример =) . Обыкновенный фильтр входящих IP . 


Цитата(boostcoder @  27.2.2011,  22:51 Найти цитируемый пост)
потому что не совпадают ожидаемая сигнатура, и предоставленная вами.


А Вы не подскажите как решить данный вопрос? 
PM MAIL   Вверх
boostcoder
Дата 27.2.2011, 23:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


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

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



Цитата(Kirgston @  27.2.2011,  22:57 Найти цитируемый пост)
Обыкновенный фильтр входящих IP

с IP - понятно. так: asio::ip::tcp::socket::remote_endpoint().address().to_string()
c TTL - для чего?

Цитата(Kirgston @  27.2.2011,  22:57 Найти цитируемый пост)
А Вы не подскажите как решить данный вопрос?  

boost::bind()
PM WWW   Вверх
Kirgston
Дата 28.2.2011, 09:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



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

Спасибо большое! Жаль что (по крайней мере для меня) это не прямо напоминает то чем оно есть. Ремоут_ендпоинт расшифровывается как удаленная конечная точка, увы но я ожидал чего то более лаконичного smile , например destination_addres() или что то в этом духе. 


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

Я не имел ввиду именно ТТЛа , это первое что пришло в голову. А так мне интересно было как узнать вообще весь хидер пакета. Чтобы максимально получить информацию о клиенте.


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

Ага, вчера им тоже пытался =) он мне начал орать что я неправильно его использую. Может действительно криво, так что поковыряю.

Кстати... я правильно "убиваю" клиента?

Код

                socket_.shutdown(socket_.shutdown_both);
                socket_.close();
                delete this;


this - класс для сессии клиента
PM MAIL   Вверх
boostcoder
Дата 28.2.2011, 11:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


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

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



Цитата(Kirgston @  28.2.2011,  09:47 Найти цитируемый пост)
я правильно "убиваю" клиента?

угу
PM WWW   Вверх
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   Вверх
boostcoder
Дата 2.3.2011, 17:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


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

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



Цитата(Kirgston @  2.3.2011,  14:05 Найти цитируемый пост)
 тогда как?

так:
Код

socket_.cancel();
socket_.close();

PM WWW   Вверх
Kirgston
Дата 5.3.2011, 19:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Всё спасибо. Кстати на будущее. 

socket_.cancel();
socket_.close();

На Вин ХР делать низя =). Вин 7 воспринимает нормально а ХР нет. Лучше просто сделать шатдаун тогда и сокет сам закроется ;). 
PM MAIL   Вверх
boostcoder
Дата 5.3.2011, 19:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


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

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



...

Это сообщение отредактировал(а) boostcoder - 5.3.2011, 19:42
PM WWW   Вверх
Страницы: (3) [Все] 1 2 3 
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Сети | Следующая тема »


 




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


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

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