Я пишу маленькие 3 сервера и 1 клиентскую программу. 2 сервера отправляют tcp-сообщения, а последний отправляет датаграммы обновления с помощью winsock2.
Мне интересно, могу ли я сделать одновременный recvfrom (), используя потоки (OpenMP или boost :: threads), чтобы 2 потока слушали из одного и того же сокета на одном и том же порту одновременно.
Я использую VC ++ 2010 на Windows7.
Спасибо за помощь.
Да, сокеты являются поточно-ориентированными, но вы должны быть осторожны. Один общий шаблон (при использовании блокирования ввода-вывода) состоит в том, что один поток получает данные в одном сокете, а другой поток — в одном и том же сокете. Наличие нескольких потоков, получающих данные из сокета, обычно хорошо для сокета 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 многопоточным?
Winsock допускает только один блокирующий вызов ввода-вывода в сокете. Более одного вызова блокировки из другого потока приведет к ошибке «WSAEINPROGRESS». http://msdn.microsoft.com/en-us/library/windows/desktop/ms740668%28v=vs.85%29.aspx#WSAEINPROGRESS.
Если вы хотите сделать параллельный запрос ввода-вывода, вы можете попробовать использовать асинхронный ввод-вывод или перекрывающийся ввод-вывод (на языке Windows). Но я думаю, что вы хотели бы параллельной обработки данных больше, чем одновременное чтение данных. В этом случае у вас может быть один поток, выдающий запросы ввода-вывода, а другие — для обработки.