Winsock2 поток безопасен?

Я пишу маленькие 3 сервера и 1 клиентскую программу. 2 сервера отправляют tcp-сообщения, а последний отправляет датаграммы обновления с помощью winsock2.

Мне интересно, могу ли я сделать одновременный recvfrom (), используя потоки (OpenMP или boost :: threads), чтобы 2 потока слушали из одного и того же сокета на одном и том же порту одновременно.

Я использую VC ++ 2010 на Windows7.

Спасибо за помощь.

5

Решение

Да, сокеты являются поточно-ориентированными, но вы должны быть осторожны. Один общий шаблон (при использовании блокирования ввода-вывода) состоит в том, что один поток получает данные в одном сокете, а другой поток — в одном и том же сокете. Наличие нескольких потоков, получающих данные из сокета, обычно хорошо для сокета UDP, но большую часть времени для сокетов TCP не имеет особого смысла. В документации есть предупреждение WSARecv:

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

Но это обычно не имеет значения, если вы используете UDP и протокол не имеет состояния.

Также обратите внимание, что WSAEINPROGRESS Код ошибки в основном относится к Winsock 1.1:

WSAEINPROGRESS: выполняется блокирующий вызов Windows Sockets 1.1 или поставщик услуг все еще обрабатывает функцию обратного вызова.

И описание WSAEINPROGRESS далее говорится:

Операция сейчас в процессе.

Операция блокировки в настоящее время выполняется. Windows Sockets позволяет выполнить только одну блокирующую операцию — для каждой задачи или потока — и если выполняется какой-либо другой вызов функции (независимо от того, ссылается ли он на этот или любой другой сокет), функция завершается ошибкой с ошибкой WSAEINPROGRESS.

Обратите внимание, что это говорит об одной операции блокировки для задачи или потока.

Кроме того, в документации для WSARecv есть дополнительное предупреждение:

Выполнение другого блокирующего вызова Winsock внутри APC, прервавшего текущий блокирующий вызов Winsock в том же потоке, приведет к неопределенному поведению и никогда не должно выполняться клиентами Winsock.

Но кроме этих предупреждений у вас должно быть все в порядке.

Обновление: добавить несколько внешних ссылок:
alt.winsock.programming: Является ли сокет потокобезопасным?
а также Часто задаваемые вопросы программиста Winsock: Является ли Winsock многопоточным?

6

Другие решения

Winsock допускает только один блокирующий вызов ввода-вывода в сокете. Более одного вызова блокировки из другого потока приведет к ошибке «WSAEINPROGRESS». http://msdn.microsoft.com/en-us/library/windows/desktop/ms740668%28v=vs.85%29.aspx#WSAEINPROGRESS.

Если вы хотите сделать параллельный запрос ввода-вывода, вы можете попробовать использовать асинхронный ввод-вывод или перекрывающийся ввод-вывод (на языке Windows). Но я думаю, что вы хотели бы параллельной обработки данных больше, чем одновременное чтение данных. В этом случае у вас может быть один поток, выдающий запросы ввода-вывода, а другие — для обработки.

1

По вопросам рекламы [email protected]