Форум программистов, компьютерный форум, киберфорум
Boost C++
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.67/6: Рейтинг темы: голосов - 6, средняя оценка - 4.67
5203 / 3176 / 358
Регистрация: 12.12.2009
Сообщений: 8,034
Записей в блоге: 2
1

Boost::asio клиет-сервер - есть ощущение, что где-то что-то блокируется, не знаю как это дебажить

18.08.2015, 22:59. Показов 1106. Ответов 7
Метки нет (Все метки)

Привет!
Область эта для меня новая, поэтому такие вопросы. Смотрите - есть асинхронный сервер(работает на одной io_service) и много синхронных клиентов. Пока для отладки запускаю локально несколько штук. Судя по логам где-то после 10 минут работы (клиенты долбятся каждые ~10 секунд, ждут ответ, пишут ответ, ждут ответ и т.д., около 5-10 сообщений туда-обратно) возникает ситуация, когда клиент выполнил write(...) и повис на read(...), а сервер все еще читает (серверу передается content-length, он читает асинхронно пока весь content-length не прочитает). И похоже, что сервер не может прочитать все данные. Поэтому сервер не пишет, а клиент ждет, что он напишет.

Судя по документации boost::asio::write не вернется, пока не запишет весь буфер (размер буфера есть content-lenght), поэтому не понятно как такая ситуация возникает, т.е. как сервер не может прочитать все данные.

Пока решил проблему при помощи deadline таймера - закрываю на сервере сокет, который работает слишком долго (т.е. потеря данных допустима), но это явный костыль.

Не представляю в какую сторону копать, есть идеи?

P.S. endless loop'ов в коде нет, dead lock'ов тоже.

Добавлено через 10 минут
Вот еще что интересно (что ломает мои предположения о нестыковке read/write) - виснет работа всех клиентов (точнее похоже сервера), а не одного конкретного. Может io_service на сервере виснет? Только не предсатвляю почему.

Добавлено через 32 минуты
еще вот - зависание сервера иногда убирается вводом в консоль (у сервер ест интерфейс, работает в отдельном потоке) чего-либо. Просто нажатия enter достаточно и сообщения продолжают посылаться.
Отдельный поток (где интерфейс) просто висит в ожидании ввода
C++
1
2
std::string cmd;
std::getline(std::cin, cmd);
Добавлено через 36 минут
Цитата Сообщение от Kastaneda Посмотреть сообщение
зависание сервера иногда убирается вводом в консоль
Баг бывает долго воспроизводится, сейчас выяснил, что достаточно просто фокуса, т.е мышкой по консоли кликнуть.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
18.08.2015, 22:59
Ответы с готовыми решениями:

Подскажите что делать. Знаю что надо перегрузить оператор но никак не могу понять как это сделать
#include "stdafx.h" #include <iostream> #include <conio.h> #include <Windows.h> #include...

При включении нетбука появляется, как бы окно, я не знаю что это такое, подскажите как можно убрать это (фото внутри)

Объясните подробно данный код программы. Знаю что это фильтр а пошагово что к чему не понимаю
void __fastcall TForm1::suiButton7Click(TObject *Sender) { tdiag -> Filtered = false; tdiag ->...

Сравниваем! Знаю что это будет R9 290, но вот какой фирмы не знаю
Ребят вот такой вопрос, на днях покупаю видеокарту, но не знаю какую, точно знаю что это будет R9...

7
Ушел с форума
Эксперт С++
16434 / 7398 / 1186
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
19.08.2015, 08:38 2
Цитата Сообщение от Kastaneda Посмотреть сообщение
Судя по логам где-то после 10 минут работы (клиенты долбятся каждые ~10 секунд, ждут ответ, пишут ответ, ждут ответ и т.д., около 5-10 сообщений туда-обратно) возникает ситуация, когда клиент выполнил write(...) и повис на read(...), а сервер все еще читает (серверу передается content-length, он читает асинхронно пока весь content-length не прочитает). И похоже, что сервер не может прочитать все данные. Поэтому сервер не пишет, а клиент ждет, что он напишет.
В порядке легкого бреда: а ты проверяешь, какие значения возвращают функции read и write
на клиентах и на сервере ? Может быть, что клиент выполнил write, но на сервер ушли не все
данные из буфера, а только часть (судя по докам Boost.Asio, такое возможно, в этом случае
write вернет ненулевое значение) ?

Вот еще что интересно (что ломает мои предположения о нестыковке read/write) - виснет работа всех клиентов (точнее похоже сервера), а не одного конкретного.
Возможно, виснут как раз таки несколько клиентов, но исчерпаны все рабочие потоки из пула.
Но тут поведение зависит от платформы и от используемых настроек Boost.Asio.
Я бы еще проверил, нет ли такого, что какие-то потоки преждевременно покидают io_service::run.

Цитата Сообщение от Kastaneda Посмотреть сообщение
еще вот - зависание сервера иногда убирается вводом в консоль (у сервер ест интерфейс, работает в отдельном потоке) чего-либо. Просто нажатия enter достаточно и сообщения продолжают посылаться.
Да, это уже странно.
А этот поток ввода - он тоже работает как часть Boost.Asio (т.е. с io_service и все такое) или
он сам по себе ?
1
5203 / 3176 / 358
Регистрация: 12.12.2009
Сообщений: 8,034
Записей в блоге: 2
19.08.2015, 09:14  [ТС] 3
Цитата Сообщение от Убежденный Посмотреть сообщение
а ты проверяешь, какие значения возвращают функции read и write
на клиентах и на сервере ?
На клиенте не проверяю, действительно нужно добавить.
Цитата Сообщение от Убежденный Посмотреть сообщение
Я бы еще проверил, нет ли такого, что какие-то потоки преждевременно покидают io_service::run
А как такое может быть? И разве в этом случае не должен вызваться деструктор сокета и подключение просто обрубится?
Цитата Сообщение от Убежденный Посмотреть сообщение
А этот поток ввода - он тоже работает как часть Boost.Asio (т.е. с io_service и все такое) или
он сам по себе ?
Просто command line интферфейс, без io_service. Но он хранит ссылку на io_service из другого потока, чтоб остановить его по команде.
0
Ушел с форума
Эксперт С++
16434 / 7398 / 1186
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
19.08.2015, 09:24 4
Цитата Сообщение от Kastaneda Посмотреть сообщение
А как такое может быть?
В Boost.Asio каждый поток из пула должен быть всегда занят какой-то работой:
accept, затем из accept_handler вызываем read, из read_handler вызываем write,
из write_handler снова read и т.п., потом shutdown/disconnect и снова возвращаемся в
accept. В этом случае поток все время загружен по самое немогу. Но стоит однажды
разорвать эту цепочку, например не вызвать очередную io-функцию из очередного
хэндлера, и поток покинет io_service::run. Чтобы этого не происходило (как вариант),
можно использовать класс io_service::work.

Цитата Сообщение от Kastaneda Посмотреть сообщение
И разве в этом случае не должен вызваться деструктор сокета и подключение просто обрубится?
Опасность не в этом, а в том, что один из рабочих потоков исчезнет из пула.
0
5203 / 3176 / 358
Регистрация: 12.12.2009
Сообщений: 8,034
Записей в блоге: 2
19.08.2015, 10:20  [ТС] 5
Цитата Сообщение от Убежденный Посмотреть сообщение
В Boost.Asio каждый поток из пула должен быть всегда занят какой-то работой ...
А, ну про это я в курсе, не там сервер постоянно io_service держит.

Добавлено через 14 минут
Вчера просто перекодил похоже, сегодня свежим взглядом на все посмотрел, вот что у меня было - на сервере сначала разбираю header'ы
C++
1
boost::asio::async_read_until(socket_, response_, "\r\n\r\n", ....); // тут вытаскиваю Content-length
потом читаю контент
C++
1
2
boost::asio::async_read(socket_, response_, boost::asio::transfer_at_least(1), 
    /*тут лямбда, которая проверяет response_.size() < content_length и перезапускает async_read пока меньше*/);
Что в итоге - если ответ небольшой (несколько байт), то он успевает прочитаться полностью при чтении header'ов и следующее чтение ждет transfer_at_least(1), но данных для чтения уже нет. Вот и висит он вместе с клиентом, который уже ждет от него данные.
Вобщем проблему с блокировками похоже решил
Осталось непонятное зависание, которое лечится нажатием enter.

Добавлено через 2 минуты
Цитата Сообщение от Убежденный Посмотреть сообщение
Опасность не в этом, а в том, что один из рабочих потоков исчезнет из пула.
Не, я к тому что если бы сокет разрушался, то и блокировки бы никакой не было.
0
1364 / 509 / 70
Регистрация: 21.07.2015
Сообщений: 1,287
25.08.2015, 18:40 6
Цитата Сообщение от Kastaneda Посмотреть сообщение
Осталось непонятное зависание, которое лечится нажатием enter.
Цитата Сообщение от Kastaneda Посмотреть сообщение
Отдельный поток (где интерфейс) просто висит в ожидании ввода
"Отдельный поток" - это стартовый поток приложения?
0
5203 / 3176 / 358
Регистрация: 12.12.2009
Сообщений: 8,034
Записей в блоге: 2
25.08.2015, 22:03  [ТС] 7
Цитата Сообщение от shmkv Посмотреть сообщение
"Отдельный поток" - это стартовый поток приложения?
нет, не main thread. А есть разница?
0
0 / 0 / 0
Регистрация: 08.07.2014
Сообщений: 10
27.08.2015, 12:57 8
Kastaneda
как можно с Вами связаться?? личка для меня не работает... меня устроит email, skype или icq - оставьте, пожалуйста, в теме один из этих контактов! жду! спасибо
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
27.08.2015, 12:57

Что изменить в скрипте? Когда-то почти сам написал, а сейчас не знаю где что поменять
Привет всем! Ребята, есть вот такой код, который присваивает ссылке класс active: ...

Mongoose vs Boost.Asio (веб-сервер)
Требуется прикрутить легковесный и быстрый веб-сервер с json для встраиваемой железки на Linux....

Асинхронный сервер и клиент Boost Asio
Здравствуйте. Попробовал написать нечто такое. Но на этом этапе чтения не происходит ничего. Дальше...

Обратный прокси-сервер с использованием boost::asio
Добрый день. Задача - написать обратный прокси-сервер. Использую boost::asio. При написании...

Boost::Asio Сделать так, чтобы сервер отвечал на запросы из браузера
Добрый день! Взял один из примеров Boost по асинхронным серверам. Данный код сервера-клиента...

Как узнать, что клиет закончил отсылать пакеты?
Забиндил локалхост, посылаю на него пакеты последовательно одной секцией sequence number, после...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2022, CyberForum.ru