LINUX.ORG.RU

Принципы создания сетевых многопоточных приложений


0

0

Господа... :)

Тут вот задался следующим вопросом - может быть кто-нибудь поделится опытом?

При программировании на C с использованием pthreads все вообщем-то просто и понятно: есть поток, который читает при помощи блокирующих системных вызовов данные из сокета, обрабатывает их и отправляет каким-либо способом в GUI. Когда, например, пользователь нажимает кнопку "разорвать соединение", вызывается функция pthread_cancel, и даже если в данный момент поток заблокирован на чтении из сокета, то он успешно убивается (нужно только позаботится об уничтожении всей выделенной им динамической памяти).

Если же смотреть в сторону C++, то в тех библиотеках, которые мне попадались, либо вообще не было возможности прервать поток, либо его можно было прервать только в тех точках программы, в которые программист вставлял специальные операторы библиотеки (аналоги pthread_testcancel), но если поток заблокирован на семафоре или ждет прихода данных из сети, то завершить его нет никакой возможности.

Как поступать в таких случаях? Ставить таймауты на получение данных и работать по следующей схеме?:

readed_bytes = 0;
while(readed_bytes != needed_bytes)
{
readed_bytes += some_recv_function_with_timeout(socket, buf + readed_bytes, needed_bytes - readed_bytes);
some_testcancel_function();
}

Вообщем-то не такой уж плохой вариант, но имеет следующие недостатки:
- невозможно для чтения использовать стандартную библиотеку ввода/вывода (в случае pthreads вполне можно использовать fread для чтения данных из сокета) для обеспечения буферизации.
- если приложение имеет графический интерфейс, то это означает что реакция на любые действия пользователя должна быть как можно быстрой, поэтому таймауты приходится выбирать маленькие, что ведет к увеличению количества вызовов тела цикла, а, следовательно, плохо сказывается на производительности.

Неужели нет лучшего варианта? Очень хотелось бы услышать мнения опытных (и не очень) программистов, которые уже сталкивались с подобными проблемами.

anonymous

Ответ на: комментарий от Deleted

Хм, спасибо. Дополнительный сокет + select - довольно неплохая идея.

anonymous
()

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

если пользоваться С++, то лучше всего смотреть на Boost.Asio - там очень грамотный дизайн, плюс получается кросс-платформенное решение. У меня есть пара небольших статеек про Boost.Asio - http://xtalk.msk.su/~ott/ru/cpp/BoostAsioNotes.html & http://xtalk.msk.su/~ott/ru/cpp/BoostAsioProxy.html

ott ★★★★★
()

Мне нравится решение, примененное в memcached -- libevent'ом создается event loop, который accept'ит клиентов и N (например по числу ядер) event loop'ов-потоков, которые работают с клиентскими сокетами. Задания worker thread'ам посылаются pipe'ом.

Код получается прозрачный, в отличие от бустов с асио.

Reset ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.