Модераторы: 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   Вверх
Страницы: (3) Все [1] 2 3 
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Сети | Следующая тема »


 




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


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

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