Если я вас правильно понял, и вы пытаетесь recv
на том же SOCKET
в параллельных потоках, тогда не делайте этого, от этого нечего получить. Данные, которые вы recv
, уже буферизуются базовой системой, и вы получаете к этому доступ, и вы можете создать несколько буферов для recv
, чтобы при возврате данных вы могли передавать один буфер в верхний уровни "для обработки и использовать другой для нового вызова recv
. Вы также можете использовать только один большой буфер с уведомлениями, что для обработки и какая часть используется для получения. Система, вероятно, имеет блокировки, которые запрещают многократное чтение в одном сокете, поэтому результат в одном recv
равен 0
. Если бы этого не было, вы, вероятно, получили бы почти случайное разделение данных.
РЕДАКТИРОВАТЬ: Полное и полное объяснение
Я думаю, что использование нескольких потоков для чтения из одного сокета бесполезно
Розетки - это программная вещь. Ваше сетевое устройство не создает никаких «подключений», оно просто обрабатывает полученные данные и упаковывает / разворачивает их в IP
(или в любое другое
поддерживаемые пакеты интернет-уровня) (предыдущий, в зависимости от сетевого устройства, некоторые из них почти полностью программно эмулируются операционной системой os и фактически выполняют только базовые услуги «write to tx-read rx», но для нас это то же самое). Сервис WinSock2
распознает пакеты с конкретными данными (как вы уже заметили), так что вы можете использовать одно сетевое устройство одновременно
общение с несколькими сверстниками. WinSock2
активно следит за трафиком, прежде чем передать его вам. Другими словами: когда вы собираетесь получить успешные recv
данные
была уже там, и базовая система проверила сокет, который вы использовали в качестве параметра в recv
, и передала вам только те данные, которые уже были помечены как данные
для этого сокета. Чтение с нескольких потоков из одного сокета (без почти бесполезного MSG_PEEK
) сделает систему, если она не имеет блокировок, скопирует неизвестное число байтов
к расположению, указанному в recv
в потоке 1, и постоянно увеличивайте внутренний указатель на данные на количество скопированных байтов, затем, перед тем, как все данные будут доступны в
recv
копируется в location1, другой поток запускает и копирует также неизвестное количество байтов, увеличивая таким образом внутренний указатель на данные на столько байтов.
Результатом этого типа чтения в идеале должна быть половина данных, хранящихся из местоположения, переданного в потоке 1, а другая половина, начиная с местоположения, переданного в потоке 2. Поскольку идеальный результат является неопределенным (время, выделенное системой для этих двух потоков, не гарантированно будет равным) вы получите несортированные данные без каких-либо средств сортировки
это, так как информация, которую базовая система использует для того, чтобы знать, какие данные принадлежат к какому сокету, вам не удастся.
Поскольку ваша система, скорее всего, работает быстрее, чем ваше сетевое устройство, я придерживаюсь двух моих решений, первое предпочтительнее, поскольку я использовал этот метод для больших и малых блоков передачи данных:
Создайте один поток чтения для каждого подключенного сокета и один циклический буфер, размер буфера зависит от размера чанков, которые вы ожидаете получить, и времени, которое вам потребуется для дальнейшей обработки содержимого, сохранения текущей позиции чтения, сохранения «обработать счет», когда данные получены, уведомить поток / потоки о том, что они должны обрабатывать данные в буфере, сохранить позицию данных, используемых для чтения, продолжить recv
, если есть буферное пространство, не обрабатываемое иначе подождите, пока это не произойдет (необходимо реализовать это в случае, если ваш компьютер где-то захлебнется, в нормальных ситуациях это не должно). Вы должны синхронизировать принимающий поток с потоком / потоками обработки, когда они обращаются к переменным "to_process_count" и "current read pos", как они покажут
Вы, какие байты вы можете использовать в циклическом буфере.
Создайте и подключите один сокет для каждого потока чтения, чтобы система могла самостоятельно регулировать данные
То, что вы тоже называете случайными потоками, читающими из одного сокета, может быть достигнуто через следующие сценарии:
1 Thread Перечисляет сокет, чтобы увидеть, есть ли доступные данные
когда данные доступны, он использует мьютекс для ожидания, если какой-то поток уже находится в состоянии чтения, запускает новый поток для чтения и для обработки существующих данных
или это может быть достигнуто с помощью чего-то подобного
Поток выполняет recv
, как только он успешно завершил recv
(да, данные находятся в буфере), он запускает другой поток из некоторого пула потоков для выполнения recv
и продолжает обрабатывать данные и завершать работу. сам
Таким образом, я могу представить, что "чтение с несколькими потоками в одном сокете" возможно. Да, не будет нескольких потоков, вызывающих recv
одновременно
Извините за длинный пост, орфографические и грамматические ошибки и надеюсь, что это вам немного поможет