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

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

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

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

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


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

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

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

Получатель:

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