Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности
|
|
|
Можно прервать select() с таймаутом из другого потока?
|
|||
|---|---|---|---|
|
#18+
Есть цикл приема-отправки UDP-сообщений. Упрощенно так выглядит: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. Для пассивного сервера подходит идеально: стоит на select() ждет входящие сообщения, тут же отвечает на них. Для клиента проблема с отправкой. Проблема из-за таймаута select() Делаю так: рабочий поток создает очередь сообщений для отправки, поток отправки в send_message() читает очередное сообщение и возвращает этому циклу, он отправляет. Но тут появляется лишняя пауза в из-за таймаута select(). Пока он не истечет - отправка не произойдет. Вопрос: можно как-то из другого потока select() вывести из ожидания? Есть варианты, которые мне не очень нравятся: 1. Запустить отправку из рабочего потока. (получится что сокет использую в двух потоках) 2. Послать из рабочего потока с другого сокета сообщение-команду на отправку, которая выведет select() из ожидания. (вообще изврат какой-то получится) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.04.2014, 14:03 |
|
||
|
Можно прервать select() с таймаутом из другого потока?
|
|||
|---|---|---|---|
|
#18+
Dima Tпоток отправки в send_message() читает очередное сообщение и возвращает этому циклу, брр.. зачем поток отправки занимается чтением? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.04.2014, 14:21 |
|
||
|
Можно прервать select() с таймаутом из другого потока?
|
|||
|---|---|---|---|
|
#18+
ИзопропилDima Tпоток отправки в send_message() читает очередное сообщение и возвращает этому циклу, брр.. зачем поток отправки занимается чтением? Читает из очереди на отправку (очередь заполняет другой поток). send_message() это моя callback-функция, которая готовит сообщение к отправке. Тут исходники если интересно. Упростил пример, чтоб не грузить ненужными деталями. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.04.2014, 14:32 |
|
||
|
Можно прервать select() с таймаутом из другого потока?
|
|||
|---|---|---|---|
|
#18+
Получается такая картина Время мсРабочий потокПоток отправки0select()10задание в очередь... ничего не происходит 90 мс 100select() выпал по таймауту101send_message() читает из очереди102sendto() ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.04.2014, 14:43 |
|
||
|
Можно прервать select() с таймаутом из другого потока?
|
|||
|---|---|---|---|
|
#18+
Dima TЕсть цикл приема-отправки UDP-сообщений. Упрощенно так выглядит: pselect умеет наносекунды. А вообще, можно использовать non-block сокеты, прокручивать запуск чтение/записи порций данных в одном потоке, по дережированию через select/pselect, и тяжёлый парсинг уже вынести в отдельный поток, связанный с реактором очередью. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.04.2014, 14:53 |
|
||
|
Можно прервать select() с таймаутом из другого потока?
|
|||
|---|---|---|---|
|
#18+
luislom pselect умеет наносекунды. я и тут могу до 1 мкс таймаут опустить, вполне устроит, только зачем гонять пустой цикл? проц грузить? Момент появления задания в очереди неизвестен. Например висим, ждем 5 часов, а потом пользователь нажал кнопку и надо как можно быстрее отправить. Тут надо что-то фундаментально менять. Как вариант отправка из рабочего потока (вызов sendto()), только не вылезут глюки какие-нибудь из-за работы с одним сокетом в двух потоках? Я этот вопрос уже задавал однажды, мнения разделились. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.04.2014, 15:26 |
|
||
|
Можно прервать select() с таймаутом из другого потока?
|
|||
|---|---|---|---|
|
#18+
Dima TТут надо что-то фундаментально менять. Как вариант отправка из рабочего потока (вызов sendto()), только не вылезут глюки какие-нибудь из-за работы с одним сокетом в двух потоках? Я этот вопрос уже задавал однажды, мнения разделились. Тогда Вам на Linux/epoll, или freebsd/kqueue. Не знаю вроде win IOCP из той же темы. Например, при использовании epoll, зависаем на epoll_wait пока не появляется на одном сокете событие, после чего пошли в цикл, если к моменту возвращения к epoll_wait на сокетах произошли события-получаем эти сокеты и снова в цикл, если таковых нет-зависаем. Ещё есть boost::asio, очень интересная игрушка. Там функиями async_read/async_write и передаваемыми в них асинхронными функциями-хендлерами, можно расписать конечный автомат который будет читать/писать по мере поступления/отправки данных. Советую именно boost::asio, он ещё и кроссплатформенный. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.04.2014, 16:08 |
|
||
|
Можно прервать select() с таймаутом из другого потока?
|
|||
|---|---|---|---|
|
#18+
luislomзависаем на epoll_wait пока не появляется на одном сокете событие select() тоже самое делает, только событие у меня НЕ на сокете появляется. Почитал инет, пишут что sendto() thread-safe. Попробую слать из рабочего потока. На всякий случай оберну в критическую секцию чтобы одновременно оба потока не слали. К тому же мой send_message() совсем не thread-safe. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.04.2014, 16:58 |
|
||
|
Можно прервать select() с таймаутом из другого потока?
|
|||
|---|---|---|---|
|
#18+
Dima Tselect() тоже самое делает, только событие у меня НЕ на сокете появляется. Нет, select гарантированно виснет на интервал времени, epoll_wait возвращает управление немедленно, если на одном или нескольких сокетах или пришли данные для чтения, или данные для отправки из буфера были все отправлены в сеть (вспомним, что говорю про non block сокеты). В противном случае спим, пока таковые события не произойдут. Почитал инет, пишут что sendto() thread-safe. Попробую слать из рабочего потока. На всякий случай оберну в критическую секцию чтобы одновременно оба потока не слали. К тому же мой send_message() совсем не thread-safe. У Вас имхо дизайн неуклюжий и неудачный. Пусть данные шлёт один поток, другие пусть занимаются обработкой. Откройте для себя асинхронные, неблокирующие операции с сокетами. Сейчас это уже стандарт. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.04.2014, 17:11 |
|
||
|
Можно прервать select() с таймаутом из другого потока?
|
|||
|---|---|---|---|
|
#18+
luislomselect гарантированно виснет на интервал времени, это и хотел услышать, как один из вариантов ответов. luislomОткройте для себя асинхронные, неблокирующие операции с сокетами. Сейчас это уже стандарт. Операции у меня асинхронные, а сокеты синхронные. А открывать я буду пиво, т.к. надоела уже эта низкоуровневая трихомудия ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.04.2014, 18:33 |
|
||
|
Можно прервать select() с таймаутом из другого потока?
|
|||
|---|---|---|---|
|
#18+
Dima T А открывать я буду пиво, т.к. надоела уже эта низкоуровневая трихомудия Это уютная верхушка. Если полезете в SOCK_RAW тогда пиво не прокатит-только грибы. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.04.2014, 19:00 |
|
||
|
Можно прервать select() с таймаутом из другого потока?
|
|||
|---|---|---|---|
|
#18+
luislomЭто уютная верхушка. Если полезете в SOCK_RAW тогда пиво не прокатит-только грибы. Туда точно не полезу, заглядывал. Если уж потребуется - найму профессионалов. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.04.2014, 19:13 |
|
||
|
Можно прервать select() с таймаутом из другого потока?
|
|||
|---|---|---|---|
|
#18+
Dima T, есть простой трюк - создать сокет только для пробуждения, http://stackoverflow.com/questions/384391/how-to-signal-select-to-return-immediately ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.04.2014, 19:53 |
|
||
|
Можно прервать select() с таймаутом из другого потока?
|
|||
|---|---|---|---|
|
#18+
ИзопропилDima T, есть простой трюк - создать сокет только для пробуждения, http://stackoverflow.com/questions/384391/how-to-signal-select-to-return-immediately Почитал, как понял там добавляют в fd_set к TCP сокету второй сокет UDP и на него шлют что-нибудь через localhost. Он принимает и выводит select() из ожидания. По сути это то что рассматривал вторым вариантом Dima T2. Послать из рабочего потока с другого сокета сообщение-команду на отправку, которая выведет select() из ожидания. (вообще изврат какой-то получится) Т.к. у меня изначально UDP, то второго сигнального не надо. Порт на localhost (куда слать) я знаю. Склоняюсь к мнению что это наименьший изврат, т.к. по первому моему варианту (слать с двух потоков) надо прописывать синхронизацию потоков, и второй нехороший момент: остановить быстро поток отправки по команде я не могу, т.к. select() висит и надо ждать пока таймаут истечет. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.04.2014, 08:16 |
|
||
|
Можно прервать select() с таймаутом из другого потока?
|
|||
|---|---|---|---|
|
#18+
Dima T, обрати внимание, во вспомогательный сокет ничего не шлют, его просто закрывают ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.04.2014, 12:43 |
|
||
|
Можно прервать select() с таймаутом из другого потока?
|
|||
|---|---|---|---|
|
#18+
Изопропилобрати внимание, во вспомогательный сокет ничего не шлют, его просто закрывают А что мешает закрыть основной? Posted via ActualForum NNTP Server 1.5 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.04.2014, 13:30 |
|
||
|
Можно прервать select() с таймаутом из другого потока?
|
|||
|---|---|---|---|
|
#18+
ИзопропилDima T, обрати внимание, во вспомогательный сокет ничего не шлют, его просто закрывают Так даже проще получилось: кода меньше и обработать можно сразу не дожидаясь пока до этого сообщения очередь дойдет (если есть другие входящие в буфере). В итоге так сделал Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. Другой поток вызывает для вывода select() из ожидания Код: plaintext 1. 2. 3. 4. 5. 6. Тут опять вопрос с многопоточностью возникает: надо дополнительно синхронизацию потоков делать? sock_wakeup это общий ресурс получается, но пишет в него только один и closesocket() никаких исключений не вызывает на закрытом сокете. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.04.2014, 14:32 |
|
||
|
Можно прервать select() с таймаутом из другого потока?
|
|||
|---|---|---|---|
|
#18+
Dimitry SibiryakovА что мешает закрыть основной? Если на этот момент будут входящие необработанные сообщения в буфере ОС, то можно будет про них забыть. И bind() придется каждый раз делать. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.04.2014, 14:35 |
|
||
|
Можно прервать select() с таймаутом из другого потока?
|
|||
|---|---|---|---|
|
#18+
Не прошла моя конструкция реальные испытания. Получилось просто, красиво и ... неправильно )) У select() разное поведение: 1. когда поток висит на select(), то при вызове closesocket(sock_wakeup) он возвращает 1 и FD_ISSET(sock_wakeup, &fd) = true (эту ситуацию мой код обрабатывает) 2. когда поток что-то делает, вызывается closesocket(sock_wakeup), затем доходит до select(), ему дается закрытый сокет, select() тут же возвращает SOCKET_ERROR (тут цикл прерывается). Причем FD_ISSET() для обоих сокетов дает true. вот версия 2.0 если кому интересно (выделил изменения) Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. Не очень красиво, на каждом входящем сообщении проверка || sock_wakeup == SOCKET_ERROR || FD_ISSET(sock_wakeup, &fd) , но похоже без этого никак. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.04.2014, 18:34 |
|
||
|
|

start [/forum/topic.php?fid=57&msg=38613238&tid=2019542]: |
0ms |
get settings: |
9ms |
get forum list: |
12ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
78ms |
get topic data: |
12ms |
get forum data: |
3ms |
get page messages: |
49ms |
get tp. blocked users: |
1ms |
| others: | 296ms |
| total: | 468ms |

| 0 / 0 |
