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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> [asio] как узнать что произошёл disconnect 
:(
    Опции темы
borisbn
Дата 22.12.2011, 09:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Всем привет.

Есть asio::tcp::socket. Коннекчусь им к серверу. Если сервер выключили или пропало соединение, то как узнать об этом ?
И ещё вопросик. Есть ли функция получения текущего состояния сокета - есть коннект / нет коннекта / в процессе коннекта / в процессе дисконнекта ?

Спасибо.


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
boostcoder
Дата 22.12.2011, 09:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


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

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



Цитата(borisbn @  22.12.2011,  09:44 Найти цитируемый пост)
Если сервер выключили или пропало соединение, то как узнать об этом ?

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

Цитата(borisbn @  22.12.2011,  09:44 Найти цитируемый пост)
Есть ли функция получения текущего состояния сокета - есть коннект / нет коннекта / в процессе коннекта / в процессе дисконнекта ?

есть is_open(). остального нет.

Добавлено через 11 минут и 25 секунд
при начале изучения asio, очень рекомендую прочесть Core Concepts and Functionality. там описываются основные принципы/концепты asio, которые необходимо знать, хотя бы для правильного формулирования вопросов.
PM WWW   Вверх
borisbn
Дата 22.12.2011, 14:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(boostcoder @  22.12.2011,  09:53 Найти цитируемый пост)
которая по завершению вызывает назначенный ей хендлер. вот в этом хендлере по переданному ему коду ты и узнаешь о типе ошибки

Вот я и подумал, что туда попадёт только по завершению, а про то, что при разрыве соединения попадёт туда же - не сообразил. Спасибо.

Цитата(boostcoder @  22.12.2011,  09:53 Найти цитируемый пост)
есть is_open(). остального нет.

Опять же, неправильно понял... Подумал, что эта функция говорит, была ли вызвана ф-ция секета open(), а не "есть ли в данный момент коннект". 2-е спасибо. Раз уж про open() зашла речь, не подскажешь, нужно ли вообще её вызывать ? Зачем она нужна ? В описании очень скупо сказано
Цитата
Open the socket using the specified protocol.

В бустовских примерах её никто не вызывает...

Цитата(boostcoder @  22.12.2011,  09:53 Найти цитируемый пост)
при начале изучения asio, очень рекомендую прочесть Core Concepts and Functionality

Ессно прочёл. От корки до корки, но т.к. не нашёл там ответов на свои вопросы, то и пришёл задавать их здесь.


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
boostcoder
Дата 22.12.2011, 14:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


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

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



Цитата(borisbn @  22.12.2011,  14:01 Найти цитируемый пост)
нужно ли вообще её вызывать ? Зачем она нужна ?

она создает внутреннюю реализацию для указанного типа IP. вообще, никогда не использовал ее)

Цитата(borisbn @  22.12.2011,  14:01 Найти цитируемый пост)
В бустовских примерах её никто не вызывает...

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


Шустрый
*


Профиль
Группа: Участник
Сообщений: 100
Регистрация: 12.1.2011
Где: Казань

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



Цитата(borisbn @ 22.12.2011,  09:44)
Если сервер выключили или пропало соединение, то как узнать об этом ?

Если нет висящей (pending, активная) операции ввода/вывода/connect на сокете, то о том, что соединение закрыто узнать трудно. Сомневаюсь, что is_open сообщит о том, что "remote peer is disconnected". Даже если на сокете есть активная операция, то о том, что кто-то порвал/выдернул сетевой шнур TCP/IP-стек сообщит не сразу (если вообще сообщит) - обычно используется application level ping/pong.
Многие вопросы отпадут, если почитать "Эффективное программирование TCP/IP" Йона Снейдера.
Удачи.
PM MAIL WWW Skype   Вверх
borisbn
Дата 22.12.2011, 16:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



mabrarov, спасибо, учту.
Цитата(mabrarov @  22.12.2011,  16:19 Найти цитируемый пост)
Многие вопросы отпадут, если почитать "Эффективное программирование TCP/IP" Йона Снейдера.

Уже начал читать. Спасибо.


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
borisbn
Дата 23.12.2011, 09:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Ну... Чтобы не плодить тем спрошу ещё разок тут.
Правильно ли я понимаю, что
Цитата
Asynchronous completion handlers will only be called from threads that are currently calling io_service::run()

означает, что результат чтения/записи/коннекта мне прийдёт в потоке, который вызвал io_service::run() ?
Если да, то каким образом мне передать управление (и данные) из этого потока в основной (для отображения графики, например) ? Курить boost::signal ? М.б. strand::wrap() ?
Код

socket.async_read(... handler ); // (1)
boost::thread t( boost::bind( &boost::asio::io_service::run, &io ) ); // (2)
...
void handler(...) {
// хочу, чтобы этот код выполнялся в основном потоке приложения
// в том потоке, в котором выполнялись строки (1) и (2)
}

Спасибо.


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
boostcoder
Дата 23.12.2011, 10:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


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

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



Цитата(borisbn @  23.12.2011,  09:21 Найти цитируемый пост)
Правильно ли я понимаю, что ... означает, что результат чтения/записи/коннекта мне прийдёт в потоке, который вызвал io_service::run() ?

да.

Цитата(borisbn @  23.12.2011,  09:21 Найти цитируемый пост)
каким образом мне передать управление (и данные) из этого потока в основной (для отображения графики, например) ?

зависит от фреймворка, который использовался для создания гуя. для куте - QMetaObject::invokeMethod.

Добавлено через 5 минут и 50 секунд
хм... хотя..глядя на код, понимаю что ты другое спрашиваешь.

один из способов:
Код

io_service main_loop;
io_service work_pool;
boost::thread t(&boost::asio::io_service::run, boost::ref(work_pool));

ip::tcp::socket socket(work_pool);
socket.async_read(... handler );

...

void handler(...) {
   // хочу, чтобы этот код выполнялся в основном потоке приложения
   // в том потоке, в котором выполнялись строки (1) и (2)
   main_loop.post( ... );
}

...

main_loop.run();

PM WWW   Вверх
borisbn
Дата 23.12.2011, 11:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



boostcoder, дело в том, что я пишу не программу, а библиотечку, и в каком она будет использована фреймворке мне не нужно знать (чисто для кути я уже сделал такую библиотечку, и "переношу" управление и данные между потоками сигнал/слотами). В частности, мне нужно, чтобы данная библиотека работала из-под дебилдера. Мой класс (строки (1) и (2) из моего псевдокода) будет создаваться в основном потоке билдера, туда же мне и нужно вернуть управление и данные.


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
boostcoder
Дата 23.12.2011, 11:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


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

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



Цитата(borisbn @  23.12.2011,  11:03 Найти цитируемый пост)
Мой класс (строки (1) и (2) из моего псевдокода) будет создаваться в основном потоке билдера, туда же мне и нужно вернуть управление и данные.

тогда основной поток должен лочится. мне не известны принципы/способы создания программ с использованием билдера.

Добавлено через 2 минуты и 9 секунд
покажи желаемый пример использования твоей библиотеки.

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


Шустрый
*


Профиль
Группа: Участник
Сообщений: 100
Регистрация: 12.1.2011
Где: Казань

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



Цитата(boostcoder @ 23.12.2011,  10:32)
зависит от фреймворка, который использовался для создания гуя. для куте - QMetaObject::invokeMethod.

Да нет же! smile
Если серьезно, то (IMHO) красивое решение для Qt я привел в asio samples - qt_echo_server. Достаточно обычной связки Qt signal + Qt slot + Qt::QueuedConnection.

Добавлено @ 12:37
Цитата(borisbn @ 23.12.2011,  11:03)
boostcoder, дело в том, что я пишу не программу, а библиотечку, и в каком она будет использована фреймворке мне не нужно знать (чисто для кути я уже сделал такую библиотечку, и "переношу" управление и данные между потоками сигнал/слотами). В частности, мне нужно, чтобы данная библиотека работала из-под дебилдера. Мой класс (строки (1) и (2) из моего псевдокода) будет создаваться в основном потоке билдера, туда же мне и нужно вернуть управление и данные.

Делать надо так же как и в Delphi (в Qt это скрывается за Qt::QueuedConnection):
  • "Проектируешь" user defined window message так, чтобы основной поток билдера понимал его и мог из него восстановить все параметры вызова.
  • Там, где вызывается твой handler, заворачиваешь в user defined window message параметры вызова, который необходимо сделать в основном (он же GUI) потоке, и PostMessage.
Очень геморно. Но на 2009 год в Delphi можно было только так.

boost::signal с передачей вызова в другой поток (что, по сути, "правильно" можно сделать только при помощи очереди) никак не поможет. Основной поток C++ Builder/Delphi крутит стандартный виндовый message loop. Так что практически единственное решение - кинуть сообщение в него. Ну а в сообщении как-то указать на сам вызов (что и с какими данными). При этом где-то внутрях Delphi можно было повеcить обработчик на Windows message (возможно, на объект класса Application - это лучше, чем на форму). 

P.S. Что за C++-программисты пошли, что не знают столь древний и почти стандартный трюк...

Это сообщение отредактировал(а) mabrarov - 23.12.2011, 12:49
PM MAIL WWW Skype   Вверх
boostcoder
Дата 23.12.2011, 13:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


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

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



Цитата(mabrarov @  23.12.2011,  12:32 Найти цитируемый пост)
Что за C++-программисты пошли, что не знают столь древний и почти стандартный трюк

возможно потому, что некоторые никогда не видели дельфи, и никогда не использовали winapi.
PM WWW   Вверх
borisbn
Дата 23.12.2011, 13:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(mabrarov @  23.12.2011,  12:32 Найти цитируемый пост)
 Что за C++-программисты пошли, что не знают столь древний и почти стандартный трюк...

Обижаешь, начальник smile
Вот мой код 2006 года (лишнее опускаю)
Код

#define NET_MESSAGE (WM_USER + 777)
NetworkBase::NetworkBase()
{
  hWnd = CreateWindow("STATIC", "", 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, HWND_MESSAGE, NULL, HInstance, NULL);
  SetWindowLong(hWnd, GWL_USERDATA, (LONG)this);
  prevWndProc = (MY_WNDPROC)SetWindowLong(hWnd, GWL_WNDPROC, (LONG)netWndProc);
}
/*static*/ LRESULT CALLBACK NetworkBase::netWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
  NetworkBase *net = (NetworkBase*)GetWindowLong(hWnd, GWL_USERDATA);
  if ( NET_MESSAGE == message )
  {
    char* pack = (char*)wParam;
    SNetCommPostInfo &from = *((SNetCommPostInfo*)lParam);
    net->onNetMessage(pack, from); // callback наружу. в основной поток
  }
  return CallWindowProc(net->prevWndProc, hWnd, message, wParam, lParam);
}
void NetworkBase::staticNetHandler(char *pack, SNetCommPostInfo &from, void *context)
{
  NetworkBase *net = (NetworkBase*)context;
  SendMessage(net->hWnd, NET_MESSAGE, (unsigned int)(pack), (long)(&from));
}

просто показалось некошерно использовать WinAPI в кроссплатформенном бустовском коде.
Думал, что этот трюк можно сделать средствами буста (передача управления и данных из одного потока в другой - читай SendMessage)


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
mabrarov
Дата 23.12.2011, 14:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 100
Регистрация: 12.1.2011
Где: Казань

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



Цитата(borisbn @ 23.12.2011,  13:50)
просто показалось некошерно использовать WinAPI в кроссплатформенном бустовском коде.
Думал, что этот трюк можно сделать средствами буста (передача управления и данных из одного потока в другой - читай SendMessage)

Ну, если подумать за boost-оводов - в каждой ОС своя очередь для основного потока, в консольных приложениях ее вообще нет -> сделать вызов в контексте основного потока без учета всех типов приложений на всех поддерживаемых ОС нереально. Хотя вот в Qt получилось. Ну так у них даже WinMain под виндой свой, да в каждом QThread может быть свой message loop. Не по-boost-вски навязывать столько всего.

Юзаешь GUI-вую библиотеку - юзай ее правила/методы вызова в контексте GUI-вого потока. smile

Это сообщение отредактировал(а) mabrarov - 23.12.2011, 14:10
PM MAIL WWW Skype   Вверх
borisbn
Дата 23.12.2011, 16:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(mabrarov @  23.12.2011,  14:07 Найти цитируемый пост)
сделать вызов в контексте основного потока без учета всех типов приложений на всех поддерживаемых ОС нереально

Подозревал это, но точно не знал. Жаль.
Цитата(mabrarov @  23.12.2011,  14:07 Найти цитируемый пост)
Юзаешь GUI-вую библиотеку - юзай ее правила/методы

Я ж говорю
Цитата(borisbn @  23.12.2011,  11:03 Найти цитируемый пост)
дело в том, что я пишу не программу, а библиотечку, и в каком она будет использована фреймворке мне не нужно знать


Ладно... А то мы уже воду ступе толчём.
Спасибо ещё раз.
Тему пока не закрываю. М.б. ещё появятся вопросы по asio - буду здесь же задавать, чтоб не плодить однородных тем.


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Сети | Следующая тема »


 




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


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

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