Разместить много wsasend на одном сокете из нескольких потоков

(вопрос скопирован с форума msdn)

MSDN говорит это:

Если вы используете порты завершения ввода / вывода, помните, что порядок вызовов, выполняемых в WSASend, также является порядком заполнения буферов. WSASend не должен вызываться на одном и том же сокете одновременно из разных потоков, поскольку это может привести к непредсказуемому порядку буфера.

Хорошо... но если я не забочусь об этом заказе, а также не забочусь о заказе, я получу его на другой стороне... могу ли я использовать его тогда? Безопасно ли вызывать WSASend из нескольких потоков? И будут ли доставлены посылки так, как я их передаю (может быть, заказано по-другому, но в комплекте)??

Например -> я отправляю [12a], [34b], [11c] и [223d] ... ([] помечает единицу, которую я передаю в WSASend за один вызов), получу ли я тогда, например, 34b, 11c, 12a, 223d? Или это может разбиться? Или я могу получить такие вещи, как 2a, 34b, 7a, 5c, ...

так что, возможно, вопрос должен быть -> это потокобезопасно? и это атомно? (Я говорю о WSASend, используемом с IOCP, поэтому перевернут)

1 ответ

Решение

Кажется, что на самом деле вызовы WSASend() не являются потокобезопасными, и что если вы намереваетесь вызывать WSASend() из нескольких потоков одного и того же соединения, то вам следует синхронизировать, чтобы только один поток фактически вызывал API в любой заданной точке (т.е. удерживать блокировку для каждого соединения вокруг вызова WSASend(). См. Этот вопрос и прилагаемый тестовый код для получения подробной информации: TCP / IP IOCP получал данные, иногда поврежденные - Visual C++ для Windows и эту запись в блоге для более подробного объяснения.

Также обратите внимание, что если вы отправляете отдельные сообщения уровня приложения, используя несколько вызовов WSASend() из нескольких потоков, у вас возникает проблема, поскольку эти несколько вызовов могут смешиваться до того, как данные будут записаны в поток TCP.

Так,

Если у вас есть 5 потоков, отправляющих "завершенные 2-байтовые сообщения", которые вы отправляете

AA, BB, CC, DD, EE и т. Д. Из 5 разных потоков, тогда вы не получите поток, содержащий

ABCCDDBAEE

но вы можете получить любую комбинацию порядка сообщений.

Если ваши потоки отправляют сообщения с несколькими отправленными вызовами, например, с тремя отправками, A1 A2 A3 из потока 1 формирует одно сообщение уровня приложения. Тогда все ставки сняты, как вы могли в конечном итоге

A1B1A2A3B2B3 и т. Д. В потоке TCP.

Если вам нужно сделать позже, вам понадобится какая-то блокировка вокруг ВСЕХ вызовов WSASend, чтобы вы могли сгруппировать несколько отправок в одну атомарную отправку уровня приложения или вам нужно использовать несколько WSABUF для одного вызова WSASend для сбора. вместе несколько записей в один вызов.

Другие вопросы по тегам