Ситуация такова. Есть сервер и клиенты. Клиент подсоединяется к серверу и сервер начинает слать клиенту пакеты. Пакеты - это кадры видеоизображения. Сервер отдает клиенту либо оригинальный FPS, либо заниженый, в случае если линия клиента не позволяет успевать забирать все пакеты. При этом механизм синхронизации таков, что сервер не ждет отстающих клиентов (мутексы/критические секции не используются). Сервер выдает отправителю кадр и сетит евент. Отправитель отправляет кадр и ресетит евент. Если эвент сигналед то сервер просто скипает отправителя. В итоге у медленного клиента FPS (теоретически) падает ровно настолько, насколько у него нехватает мощей сети. В локалке все работает без проблем. Но вот когда сервер в США а клиент в России, возникают непонятки. Устанавливая различную степень сжатия кадра можно получить различные размеры пакетов (пакет = кадр, пожатый jpeg-ом). Так вот, в зависимости от размера кадра меняется скорость трафика. Например, при размере кадра в 70-75 кб я получаю 3.3 FPS, то есть где-то 247 кб/с. Уменьшив размер кадра в 10 раз до 7-7.5 кб я получаю 10.2 FPS, то есть где-то 75 кб/с. То есть скорость трафика упала где-то в 3.5 раза. Вот это и непонятно. В оригинале сервер имеет 30 FPS, поэтому мой клиент отстает во всех случаях. Это значит что теоретически скорость трафика должна бы быть одинаковой (в кб/с). Откуда может возникать эта задержка? Отправка происходит по TCP в отдельном потоке через блокирующий сокет. Один пакет отправляется одним вызовом send.
Вот еще интересная информация. У меня канал 4 мегабита, то есть 512 кб/сек. При определенном качестве запущеный клиент выдает 70 кб/с, при этом выдавая 10 FPS. То есть клиент типа не успевает за сервером. Но если запустить например пять клиентов, то каждый выдаст 70 кб/с, или что еще смешнее - скорость может даже вырасти. С первого взгляда похоже что чем меньше размер пакета, тем медленнее суммарный трафик (кб/с). Если делать буфферизацию, то придется синхронизировать вывод по таймстемпам. Сейчас этого пока что делать не хочется - я вывожу кадр сразуже после его получения. Кроме того при буферизации будет сложнее скипать кадры если инет реально не вытягивает поток.
В общем основной вопрос такой: большими блокирующими сендами трафик уходит быстро, а маленькими - медленно. Хочется научиться отправлять маленькие пакеты со скоростью больших
Есть такая вещь как handshake- в переводи рукопожатие оно и тормозит. UDP отсылает пакеты без подтверждения. Поэтому тут должно работать быстро. С TCP обстоят дела иначе тут есть ответ, о том что пакет дошел. При потоковой отправки ответы идут в разнобой. Компьютер не ждет подтверждения прежде чем отправить следующий пакет. А если отпровлять не потокам, а датограммами то будет ждать ответа о приходи пакета. А вообще TCP можно попробовать обхетрить. Правда как не знаю. Поэтому можешь переходить на UDP и организовывать свой протокол.
Pavia Дело в том, что вся работа идет по keep-alive соединению. Я не инициирую соединение на каждый кадр. Вся работа идет по постоянно живущему соединению. Хочется понять чем таким критичным один сенд в 1 метр отличается от 10 сендов по 100 кило.
Уверен? Я сталкивался с подобным, когда был программный хендшейк между сервом и клиентом. То есть на каждый блок приходил респонс, и принимающая сторона с ним синхронизировалась.
Объесняю. На пальцах на примере реальных данных. Дупустим нам надо отправить 70кбайт. Размер пакета пусть 10Кб хотя реально наверно 8 или 2кб. Так вот мы отправляем сразу все 70кб. Паралельно ловим пакеты подтверждения полный дупликс. Код (Text): 1_ушел 2_ушел 3_ушел 4_ушел 5_ушел 6_ушел 7 ушел ждем ждем ждем ждем ждем 1_пришел 2_пришел 3_пришел ждем 4_пришел 5_пришел 6_пришел 7_пришел так вот грубо говоря мы потратили 7 едениц времени на отправку и в это время поймали 4 подтверждения. И еще потратили в ожидании 3 едениц на подтверждение итого7+3=10 Теперь отправим 7 покетов по 10 Код (Text): 1 ушел ждем 2_ушел ждем 3_ушел ждем 4_ушел ждем 5_ушел ждем 6_ушел ждем 7_ушел ждем ждем 1_пришел ждем 2_пришел ждем 3_пришел ждем 4_пришел ждем 5_пришел ждем 6_пришел ждем 7 пришел 7+7=14 Как видно скорость упала в 1.5 раза Хотя если брать в идеали то должна была (7+7)/(7+1)=14/8=1,75 НО это без учета всяких там помех. Задержек потерь пакетов и прочего.
Booster Уверен, потому что и клиент и сервер от и до написаны мной. Pavia Тогда такой вопрос - а в неблокирующем режиме ведь по сути не будет никаких отиличий между юзерскими пакетами? Может нужно просто неблокирующие сокеты взять?
_DEN_ Используй UDP там нет подтверждения о приеме. Можно и через TCP, но тут буфер вводить. Это недолжно помочь. Хотя попробовать можешь.
Booster Если инет клиента не вытягивает 30 FPS, то как ему смотреть видео? Видео не должно отставать от источника. Pavia Да, буффер ввести можно и это поможет 100%, вот только тогда отображение кадра придется синхронизировать по таймстепму. Пока что делать этого не хочется. Сейчас пока что "принял и сразу показал".
Из-за подтверждения доставки. TCP - протокол, гарантирующий доставку данных, т.е. в теории клиент после получения очередного пакета должен слать на сервер подтверждение, что эти данные он получил. На практике, при хорошем качестве связи, подтверждения отсылаются через n пакетов, где n=1...дофига При использовании блокирующих сокетов или евентов, завязанных на окончание отправки данных, стек TCP ждет получения подтверждения доставки, иначе он не может гарантировать, что данные были приняты клиентом, а не потерялись по дороге. Если отправлять данные маленькими порциями, получаем избыток пакетов подтверждения доставки и соответственно снижение скорости на 1 пинг на каждый send.
Чтобы выиграть скорость за счет больших блоков, не обязательно делать из одного размера. Проблема в другом. Упаковка кадров в большие блоки приведет к прыганию FPS на клиенте.