Comments 41
Вне хабра проскочил вопрос «передачи параметров времени и лимита пакетов. Где в OpenConnection указываются те самые 10 second?» Я думал, что это и так понятно, но, на всякий случай, поясню тут и пойду спать (:
<packet id><type id><first arg — time><second arg — count> — всё... А как кодировать? Можете предложить варианты!
Он поверх TCP работает? Если нет то как будут разруливаться потери\дублирование\изменение порядка пакетов?
Нет, сразу поверх IP. Читайте внимательней :)
Я так и предположил, но что тогда по второму вопросу?
Если открыли соединение на 2 пакета, потом клиент отправил 1 пакет а он пришел на сервер дважды - соединение закроется? А если пакет потерялся - соединение наоборот будет висеть до перезагрузки сервера? Что если потеряется EndPacket\OpenConnection\ExtendConnection - во всех случаях будут либо висящие соединения либо прием пакетов без соединения? Тогда я не понимаю чем это лучше UDP.
Потери сугубо приемлемы, что уже упоминалось, а дублирование и, возможно, сохранение порядка можно ввести в протокол. Думаю не будет ничего сложного, если добавить ещё пару простых счётчиков входящих и исходящих пакетов в подключении, а также добавлять текущее значение исходящего в отправляемые пакеты, чтобы на той стороне сверялись и отбрасывали дубли либо ожидали предыдущие. Предугадывая вопрос, безусловно необходимо подумать ещё и над сохранением целостности пакетов.
P.s. Извиняюсь, я вообще не заметил второй вопрос (вторые сутки на ногах ;).
потери DataPacket делают бесполезным открытие соединение на заданное число пакетов, так что можно выкинуть его из протокола и оставить только время.
Потери EndPacket делают бесполезным этот тип пакетов в принципе. Зачем нужен пакет который ничего не гарантирует?
Потери OpenConnection\ExtendConnection можно разрулить повторной отправкой по таймауту пока не пришел ответ.
Но это:
надо описать в протоколе (а не описывать только идеальную ситуация когда все пакеты доходят)
Раз в N минут будет возникать затык равный таймауту(*2 и больше) при плохом соединении, при этом доставка собственно данных все равно не гарантируется.
и нет, передача данных когда каждый DataPacket ждет подтверждения от сервера будет сильно менее эффективна чем в TCP, так что для надёжной передачи эффективнее использовать TCP.
кстати, а чему этот самый таймаут равен? захардкожен в реализации? определяется по результатам пинга?
Выкидывание заданного числа пакета не одобряю, это необходимо, чтобы не пытаться в последнюю секунду отправить последний пакет, если нужно.
EndPacket — сугубо информационный пакет, он уведомляет, что больше ты не будешь отправлять пакеты. Иначе говоря, от его потери ты не станешь отправлять пакеты ещё. Хотя, его потеря неприятна, так как получатель мог бы не ждать от тебя пакетов.
Таймаут, который активируется лишь при ненулевом счётчике пакетов, но вышедшим временем жизни подключения, как я уже говорил в другом комментарии, также указывается в OpenConnection, но не изменяется в ExtendConnection.
В остальном, я не совсем понял о чём речь. Действительно, описывать лишь идеальную ситуацию не есть гуд, но то же самостоятельное подтверждение получения пакетов не обязательно должно быть на каждый пакет, ведь важно слово «самостоятельное» (можешь и лучше их пачками подтверждать, если тебе оно нужно).
Про число пакетов. Я не вижу сценария в котором "ожидать н пакетов" принципиально отличалось бы от "ожидать 999 дней" (с учетом того что любой пакет может потеряться). Сможете привести такой сценарий?
С EndPacket аналогично - во всех сценариях которые я могу представить он просто служит небольшой оптимизации - "если дойдет тогда другая сторона закроет соединение чуть раньше, не дойдет - все равно закроет по таймауту"
Клиент отправил ExtendConnection, ответ от сервера не пришел (либо потерялся запрос, либо ответ на него).Что делать клиенту? Я предположил что надо выждать н миллисекунд (скажем пинг измеренный ранее*2) и заново отправить запрос. Ок, есть другой вариант - слать раз в минуту ExtendConnection(10 минут) вперемешку с данными и не дожидаясь ответа надеяться что хоть один из десяти пройдет. Если 9 не прошли можно даже начинать "паниковать" и слать их раз в минуту, тогда вопрос с таймаутом снимается (конечно ExtendConnection должен перетирать время а не прибавлять, иначе избыток будет набегать).
В текущем виде протокола не вижу преимуществ над UDP. Любые гарантии доставки/упорядоченности пользователь должен реализовывать сам поверх протокола и в JPP и в UDP, смысл от ограничения на число сообщений в JPP неясен учитывая сказанное выше, ну а таймаут из JPP легко реализовать и на UDP - сервер может рвать соединение если от клиента не пришло пакетов в течении н секунд, а клиент слать пустые пакеты раз в секунду даже если нет данных для обмена.
Просто замечу, что это неприятно — ставить timeout на 999 дней... Смысл в том, чтобы гонять любые данные условные пять минут, а когда они закончатся, отправлять либо все необходимые для завершения обмена данные не обращая внимания на время (иначе пришлось бы пытаться попасть в последние секунды, со всеми вытекающими ;) либо отправить ExtendConnection, чтобы продолжить обмен (и в конце-концов прийти к первому варианту).
И вы правы, это просто оптимизация! И EndPacket, и вся идея :)
Третий пункт... это в принципе неправильная логика и мышление. Установи примерно нужное тебе время в самом начале, а потом уже, если поймёшь, что его не хватит (элементарно, потому что подходит к концу), расширяй подключение. Не пришёл ответ? Пробуй снова! Всё равно не получилось? Создай новое подключение! Нет? А оно тебе вообще нужно?
Если и с учётом этого комментария я вас не переубедил, то мне пожалуй нечего вам сказать. Возможно, вам моя идея действительно полностью бесполезна ;)
неприятно — ставить timeout на 999 дней
По-моему еще неприятнее ставить ограничение 10 пакетов, чтобы дошли 9 (последний по-любому подтвердить не выйдет т.к. при успешном приёме он закрывает соединение) и в итоге результат был тот же как от 999 дней.
Установи примерно нужное тебе время в самом начале
Бывают ситуации когда время известно? Даже браузер не знает сколько времени будет качать страницу, может там гифка гигабайтная. Зато он узнает что пора закрывать соединение когда докачает.
Возможно, вам моя идея действительно полностью бесполезна ;)
Судя по комментариям она бесполезна всем)
А почему последний из десяти нельзя подтвердить? Если вы про то, что десять пакетов отправлено, значит нужно закрыть, то вы забываете про входящий счётчик. Уточню, если некорректно понято: OpenConnection и ExtendConnection сообщают твои намерения, в случае со временем жизни — сколько ты предлагаешь сделать время жизни подключения в общем, с чем либо соглашается получатель (СтароеЗначение += НовоеЗначение; у вас обоих), либо отклоняет (СтароеЗначение; у вас обоих), а счётчик пакетов — сколько ты хочешь отправить пакетов. То есть, другая сторона также попросит расширения подключения на десять пакетов, чтобы позже подтверждать твои (и ответ на твой последний ты, соответственно, будешь также ждать).
По поводу известности времени в самом начале — тебе и не нужно знать его. Повторюсь, достаточно поставить условные 5 минут: хватит — прекрасно, нет — расширяй, много — отправляй EndPacket, может отправят его тебе в ответ и закроете подключение.
Эй-эй-эй, не надо так категорично :)
То есть, другая сторона также попросит расширения подключения на десять пакетов, чтобы позже подтверждать твои (и ответ на твой последний ты, соответственно, будешь также ждать).
В любом случае один из пакетов в этом цикле подтверждений будет самым последним. И его подтвердить уже не выйдет, на то он и самый последний. Соответственно если он не дойдет - соединение останется висеть. Если не согласны - напишите пример сессии когда клиент завершает соединение (с пакетами подтверждений).
СтароеЗначение += НовоеЗначение; у вас обоих
что если пакет ExtendConnection дошел (и время соединение у сервера увеличилось), а вот ответ на него - нет (и соответственно клиент все ще думает что время не выросло). В текущем виде протокола это будет приводить что избыток времени соединения будет расти, и чем хуже связь тем быстрее. Да, это
можно легко пофиксить, но пока не пофикшено.
Эй-эй-эй, не надо так категорично :)
Это связано с отсутствием ответа на четвертый вопрос. Я могу представить себе преимущества JPP по сравнению с TCP - он проще, не нужно всех этих заморочек с окнами и экспоненциальными откатами. Хотя после всех доработок завершение соединения может стать посложнее чем в TCP, но не суть.
Я не вижу преимуществ у JPP по сравнению с UDP - гарантии там те же, таймаут в UDP реализуется без всяких служебных пакетов, а работоспособность схемы с ограниченным числом пакетов вы пока не обосновали.
Ты отправил пакет, он не дошёл, а потому тебе не отправили подтверждение. Итак, с чего бы тебе либо получателю закрывать подключение со своей стороны? До него пакет не дошёл и он считает, что договорённость ещё не выполнена, у тебя также договорённость не выполнена, ведь пакет-подтверждение от него не пришёл, так как не был вообще отправлен.
Кхе, честно говоря, я не подумал об этом сценарии... Неловко вышло.
Действительно, если задуматься, то с мелкими оговорками UDP тот же. По принципу JPP, вообще, можно и проще сделать просто протокол из одного DataPacket без каких-либо гарантий (и/или гарантией доставки), переложив всё на плечи пользователя... Иначе говоря, я подумаю как сделать его лучше.
Дело осталось за малым - представить, что будет с дропом, джиттер, реордером, изменением источника в сессии, нужна ли абстракция, подобная порту, или хватит только абонента, ну и сущая мелочь, убедить хуавеи и циски, что им это надо/
Неплохо было бы почитать про особенности работы компьютерных сетей, чтобы такую наивную дичь не постить.
В текущем виде (особенно с подсчетом пакетов) совершенно непонятно, как протокол должен работать с учетом переотправки потерянных пакетов.
Также, при таком дизайне можно заддосить сервер, открыв множество соединений на длительное время.
Не понимаю, что вам непонятно в переотправке потерянных пакетов: по-умолчанию нет никаких механизмов на этот случай, но если вам необходимо, то можно элементарно присылать DataPacket в ответ, разве нет?
Что же насчёт ддоса, то он возможен и в TCP, и в UDP, так как решается не на этом уровне и достаточно просто: ты можешь отбраковывать неугодные тебе одиночные пакеты (в том числе, и на открытие соединения). Даже по причине подозрительной активности у отправителя...
Кстати, а что наивного-то? :)
Поэтому и стоит сначала ознакомиться со спецификацией TCP и понять, какие проблемы этот протокол решает, прежде чем выдумывать свой протокол, который просто не будет работать в реальных условиях.
В этом и заключается Ваша наивность - эффект Даннинга - Крюгера.
Как уже говорил ниже, это лишь сырая и обобщённая идея, которая и нужна для этого — чтобы повысить компетенцию, начать дискуссию и, возможно, получить нечто стоящее. С конкретным эффектом же вы промазали, я вполне себе осознаю свою некомпетентность и довольно поверхностное знание в данной теме... Что скажете? :)
Не нашел в статье ответа на вопросы:
в каком сценарии использования наличие заранее заданных ограничений по времени/числу пакетов будет полезно?
как планируется выбирать эти ограничения с учётом нестабильной работы сети?
Я тоже не понял главным образом, зачем это нужно. Поддержка таблицы соединений стоит денег, зачем это, если цель – просто передавать пакеты?
Насчёт таблицы соединений — осмелюсь заметить, что даже для UDP она поддерживается, просто самими провайдерами и в, так сказать, корыстных целях :)
Соглашусь, что этот протокол залез ещё и на уровне выше (уровень сессий)... но в данном случае — это достаточно обосновано и просто, идя как лёгкий довесок. Нет/да?
Всё достаточно элементарно по вашим вопросам:
В любом. Это как сервисные пакеты для проверки соединения в том же TCP, но ты сразу и чётко знаешь сколько их будет или как долго будет соединение. Можете воспринимать это как контракты, например.
Методом научного тыка?.. Не уверен, честно говоря, всё-таки представлял это как: открыл соединение на N минут (предположим, N=5), через N-1 расширил соединение ещё на N, если необходимо, и так на протяжении всей работы. Можно даже производить простенькие вычисления, чтобы не накапливался остаток.
Я ответил?
Не вижу сходства. Сервисные пакеты отправляются строго по мере надобности.
Ключевой момент именно в этом: на транспортном уровне мы не знаем, что, сколько и как долго собирается передавать приложение. В лучшем случае эта информация будет доступна на уровне протокола самого приложения, подобно Keep-Alive в HTTP. И даже там она передаётся "по факту", без попыток угадать заранее.
А угадать будет непросто. Сеть подтормаживает, и наша прикидка о длительности сессии оказалась некорректной. Соединение разорвётся, несмотря на работоспособность сети? Пользователю это не понравится.
Далее, а что подразумевается под пакетом? IP пакет? Тогда сразу встаёт вопрос: как быть с фрагментацией пакетов? Фрагмент считается за пакет? Как быть с повторной отправкой?
И это все при условии что приложение вообще знает, сколько точно данных и как долго оно будет отправлять. Я вообще навскидку затрудняюсь назвать такой сценарий, кроме разве что передачи файла заранее известного размера. Так это всего один сценарий, из-за чего огород-то городить?
Конечный итог будет простой: приложение будет брать параметры с бааальшим запасом. И тогда ваш протокол мало чем будет отличаться от того же TCP.
Как будто бы надёжности в этом протоколе нет, да и подделать пакеты третьей стороной в сессии не представляется сложным. Будущее конечно за оптимизацией, но к сожалению не в мире сетевых технологий)
Действительно, насчёт механизмов против подделки не было упомянуто, так как они отсутствуют, но их достаточно просто реализовать (как пример: подписью и её проверкой поверх протокола). Возможно, можно сразу учесть и обозначить этот функционал в протоколе... Но я не совсем уверен, стоит ли.
А вот оптимизации нужны и будут даже в сетевых технологиях, вопрос в том какие, как и когда. Разве нет? ;)
Забыли упомянуть какой из фатальных недостатков имеющихся протоколов ваш решает.
Так сказать, сравнительный анализ провести.
Фатальных? Скорее всего, никакой. Увы, но это просто нечто вроде оптимизации (приводя аналогию, замена неумелого бумажного самолётика на сделанный более аккуратно и ровно ;)
Я так понимаю старый мем вы не узнали :)
Я как раз это и имел ввиду - в чем заключается оптимизация? Что в имеющихся протоколах на ваш взгляд сделано более неумело? Вот этого анализа не хватает.
Почему то мне кажется что это какое то подражание quick.
Статья представляет из себя большой мысленный эксперимент. Надо бы всё-таки чё-нибудь написать. Причём на Си я бы не советовал. Возьмите библиотеку scapy на Питоне, опишите её средствами структуру пакетов, с её помощью сбилдите несколько примеров сессий, сохраните в PCAP. Потом можно будет добавить поддержку в Wireshark через Lua-скрипт, чтобы можно было посмотреть на это в удобной форме.
К моменту, как всё это сделаете, возможно, у вас появится понимание проблем протокола и, возможно, идеи, как это чинить.
Очень нравится читать подобные неопытные наброски, т.к. я также неопытен и интересно как разбирают в комментариях. Благодарю!
и где теоретическое моделирование? статистические оценки на реальных данных несущих сетей? примеры применения полезного где?
Это сырая идея, имейте совесть! В самом деле, у меня нет возможности и желания проводить подобное «глубокое расследование», да и в этом нет никакой необходимости. ;)
P.s. Полезное применение такое же как у остальных протоколов того же уровня — везде где они используются. А если вы про «почему он лучше старого», то я уже упоминал, что лучше простотой, локаничностью и конкретизацией ожиданий по пакетам.
Как человек, поработавший с достаточным количеством самых разных сетевых протоколов, вынужден согласиться со всей критикой выше.
На мой взгляд, проблемных момента в вашем предложении два.
Во-первых, так дела не делаются =). Недостаточно просто придумать пару заголовков и мол ну что вы пристали, это пока только идея, сейчас подумаю как это вообще может работать и зачем это может быть кому-нибудь нужно.
Протокол (и особенно базовый транспортный) должен не просто решать какую-то абстрактную задачу в вакууме, типа мы добавили возможность указать количество пакетов чтобы знать сколько нужно ждать пакетов, авось кому-нибудь пригодится. Он должен решать конкретную, практическую проблему, которую неэффективно и/или приходится постоянно раз за разом решать уровнем выше или ниже.
Во-вторых, почему собственно транспортный уровень? С самого начала речь идет о времени сессии и о количестве сообщений, большая часть отмеченных в комментариях проблем из-за недостаточного на транспортном уровне контекста, решать эти проблемы предлагается уровнем выше. По-моему очевидно, что вся затея на самом деле должна быть как минимум на сеансовом, если не вообще на прикладном уровне. Вот там -- пожалуйста, таймауты и предполагаемое количество сообщений могут быть полезны. Или нет.
Выпускная работа выпускника курсов с госуслуг?
Новый транспортный протокол? JPP — Just Packet Protocol