Подождите, пока все данные не будут получены, прежде чем отправлять другой блок

Я использую GSocket под Windows. Для тех, кто не знает, базовый сокет изначально является дескриптором типа winsock2.

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

Простой звонок во сне, кажется, работает. Это позволяет мне одновременно обрабатывать входящие фрагменты файлов при обработке других промежуточных пакетов. Излишне говорить, что это очень надежный неоптимизированный черновой вариант решения с неполным разрешением. Я тоже пытался ждать G_IO_OUT условие, чтобы стать правдой, используя обертку, похожую на знаменитый select(), Проблема заключается в том, что он позволяет отправлять три блока, а затем останавливается навсегда, поскольку данные больше не могут быть записаны.G_IO_OUT предназначен для маскировки, когда данные могут быть записаны с использованием неблокирующих отправок. Это может быть полезно, чтобы указать, заполнен ли буфер, но не пуст ли он. Также стоит упомянуть, что я определенно не хочу отправлять подтверждение от получателя отправителю о том, что он получил чанк. Это добавляет много дополнительной сложности и в конечном итоге замедлит передачу файла дальше.

Итак, что я могу сделать, чтобы заблокировать функцию отправки до тех пор, пока все имеющиеся данные не будут отправлены и получены удаленным пользователем без существенной задержки для получателя?


Вот иллюстрация того, как моя архитектура работает и предназначена для работы:

Отправитель:

  • Отправляет запрос (FILE_PROPOSAL) с размером ожидаемого имени файла
  • Отправляет имя файла
  • Отправляет запрос (FILE_INCOMMING) с размером ожидаемого файла
  • Посылает файл в виде функции потока для каждого чанка, чтобы я мог ввести синхронизированную задержку между вызовами отправки. Отправляет запрос FILE_CHUNK с типом + идентификатор файла перед каждым необработанным фрагментом.

Получатель:

  • Получает запрос (FILE_PROPOSAL) с размером ожидаемого имени файла
  • Получает имя файла
  • Получает запрос (FILE_INCOMMING) с размером ожидаемого файла
  • Выделяет структуру, содержащую информацию о файле (включая идентификатор)
  • Возвращает
  • Получает запрос (ы) FILE_CHUNK(S) с идентификатором и размером фрагмента, а затем сам блок и добавляет его в выделенный буфер в выделенной структуре.
  • Возвращает, предоставляя контроль получателю, чтобы иметь возможность обрабатывать другие запросы,

0 ответов

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