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

У нас есть приложение C++ для отправки и получения сообщений WebSocket.

Но в этих двух потоках используется один и тот же дескриптор WebSocket. Вызовет ли это какие-либо проблемы? Я не знаю, должны ли мы справиться с этим по-другому. Это работает в нашем приложении — мы можем отправлять и получать сообщения — но я не знаю, будут ли проблемы в производственной среде. У кого-нибудь есть лучшие идеи?


person Sukhas    schedule 10.02.2017    source источник
comment
Если потоки не оба отправляют или оба получают, то для обычных сокетов это не будет проблемой. Веб-сокеты более сложны, поэтому это действительно зависит от самих функций и того, что происходит на уровне фреймворка вне вашего контроля. К сожалению, документация MSDN не говорит ничего конкретного, что я мог бы найти, и это заставило бы меня использовать некоторую форму синхронизации.   -  person Some programmer dude    schedule 10.02.2017


Ответы (1)


Как и на большинстве платформ, почти все системные вызовы Windows API не обеспечивают барьеров потоков, кроме предотвращения одновременного доступа к ключевым частям ядра. Хотя я не могу сказать наверняка (документация, похоже, не отвечает на ваш явный вопрос), я был бы удивлен, если бы WinHTTP API предоставляет барьеры, которые не позволяют нескольким потокам наступать друг на друга (так сказать), особенно потому, что на самом деле это просто " helper" API, который напрямую использует вещи Winsock несколько более низкого уровня, и я бы взял на себя реализацию необходимых барьеров.

Мне также интересно, почему вы используете потоки таким образом для начала. Я практически ничего не знаю об API WinHTTP, но заметил WINHTTP_OPTION_ASSURED_NON_BLOCKING_CALLBACKS, что наводит меня на мысль, что вы можете реализовать асинхронный подход, который предотвратит любые проблемы с потокобезопасностью (и, вероятно, будет намного быстрее и эффективнее памяти).

Похоже, что механизм обратного вызова для WinHTTP довольно выразителен. См. WINHTTP_STATUS_CALLBACK. Предположительно, вы можете просто использовать неблокирующую операцию, создать прослушиватель событий и связать дескриптор соединения с dwContext. Никаких потоков.

person mr.stobbe    schedule 10.02.2017
comment
Спасибо за ваш ответ. Мы использовали потоки, чтобы нам не нужно было блокировать основной поток, ожидая прибытия сообщения. Я думаю, мы можем реализовать обратный вызов для получения сообщений. Но я не уверен, как сделать отправку сообщений асинхронной, кроме использования потоков? - person Sukhas; 10.02.2017
comment
В неблокирующей модели ввода-вывода основной поток не будет блокироваться. Он опрашивает события ввода-вывода прямо или косвенно (через зарегистрированные обратные вызовы). В какой-то момент программа спрашивает API: Эй, у тебя есть что-нибудь для меня? и API отвечает «да» (потенциально запуская обратные вызовы) или «нет». В API Windows много раз этот опрос происходит во время цикла сообщений главного окна несколько незаметно. Опять же, я ничего не знаю о WinHTTP, но при беглом взгляде кажется, что вы можете сделать что-то подобное. - person mr.stobbe; 10.02.2017
comment
Что ж, позвольте мне немного пояснить, что я имею в виду под неблокировкой... она будет блокироваться, когда выполняет работу ЦП, но не будет ждать ввода-вывода. Как правило, именно то, что вам нужно для чего-то вроде ввода-вывода через сокет, если вы не сидите и не ждете чего-то вроде изменения размера изображения или какой-либо другой дорогостоящей задачи. Большинство задач обработки сообщений и ответов практически не занимают времени. Если это займет время, создайте пул рабочих потоков в модели потребитель/производитель, который не будет блокировать основной поток и чья работа будет заключаться в выполнении этих дорогостоящих задач. - person mr.stobbe; 10.02.2017
comment
как насчет отправки сообщений. Нужно ли для этого иметь отдельный поток? или его можно отправить из основного потока? Основная проблема, которая у нас есть, заключается в следующем. У нас есть один дескриптор WinHTTP/WebSocket, который нам нужно использовать как для отправки, так и для получения. Я понял вашу идею использования обратного вызова для получения. Но как насчет отправки сообщений? Что вы думаете об этом? - person Sukhas; 13.02.2017