gzhegow
@gzhegow
aka "ОбнимиБизнесмена"

В каких случаях fread/fwrite для стрима (сокета) разумнее сделать чанками? А когда наоборот — обязательно завершить чтение/запись?

Пишу клиент для приложения, которое работает на tcp сокете.
Клиент может как получать, так и отдавать большое количество данных.

С одной стороны понимая, что опрос всех соединений в пуле будет происходит по очереди и чтобы одно из них не простаивало разумно в каждом шаге опроса отсылать например 1024 байта, в следующем шаге - еще 1024...

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

Осложняет так же то, что в приложении для которого клиент реализовано понятие "подписки". Если я из одного клиента отправлю подписку на три топика, каждый топик может получать ответы. Это значит что если я реализую отправку по чанкам, мне почему-то кажется, что до приложения может дойти каша. Впрочем насчет каши я сделаю пул соединений и в каждое чанками будет отсылаться то что нужно отправить именно в это соединение.

Но меня смущает чтение (может там так же будет, коль скоро я отправляю по очереди, то и ответы будут приходить в том же порядке и все нормально?). Отсылая команды по кусочкам, некоторые будут отосланы, соответственно придут на них ответы или подтверждения. А понимая что я считываю чанками (да еще и по нескольким топикам), может прийти тоже каша (опять же не уверен, может и нормально будет).

Соответственно как правильно разруливается такая работа считывания записи понимая, что в каждом шаге будет происходит отправка и получение только части информации?
  • Вопрос задан
  • 92 просмотра
Решения вопроса 1
VoidVolker
@VoidVolker
Dark side eye. А у нас печеньки! А у вас?
Вы явно недостаточно изучили механизмы работы сокетов и методы работы с ними. Есть два основных механизма: блокирующая передача/прием и не блокирующая передача/прием (в разных ОС есть свои ньюансы, которые можно прочитать в документации). Т.е., в первом случае поток приложения, которое принимает/передает данные, ожидает окончания передачи или приема данных, а во втором же случае приложение просто передает буфер системе и далее занимается уже своей работой. А вот уже как и с какой скоростью данные будут переданы или приняты - это уже работа операционной системы, а по окончании передачи/приема - либо ОС уведомляет приложение о том, что столько-то данных лежит в буфере - надо забрать, в случае приема либо приложение само проверяет периодически сколько там байт уже в буфере лежит. Аналогично с передачей данных - приходит уведомление о том, что данные переданы (колббэк или еще как - не принципиально в данный момент). В общем случае надо организовать очередь и пул "воркеров" - потоков, которые будут заниматься передачей данных между приложением и системой. Т.е., прочитали блок данных с диска - отправили в очередь, а первый освободившийся воркер эти данные передаст. Аналогично с приемом - воркеры принимают данные и складывают в очередь, а приложение забирает их из очереди. Само собой, в очередь надо класть не безымянный блок данных, а вместе с информацией о том, откуда и куда эти данные, а так же номер блока и общее их число. Число воркеров обычно соответствует числу ядер процессора или на один меньше и работают они все тоже асинхронно с сокетами. Воркер может быть и один, если не стоит цель максимально утилизровать процессор и сеть.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
YCLIENTS Москва
от 200 000 до 350 000 ₽
Ведисофт Екатеринбург
от 25 000 ₽
ИТЦ Аусферр Магнитогорск
от 100 000 до 160 000 ₽