Как минимум, чтобы не держать на каждом устройстве таблицу MAC-адресов всего мира, и не придумывать в каждой программе костыли по разделению потока данных на пакеты и обратной сборке из них.
@ceyt > не придумывать в каждой программе костыли по разделению потока данных на пакеты
чё ты несёшь-то вообще? Какие потоки данных? Изначально есть потоки пакетов, куда ни посмотри. И их каждая программа пытается высрать в поток байтов, а потом из потока байтов всрать обратно в поток пакетов. И именно разделение и сборка являются самым сложным делом, а ещё гарантии доставки, реконнекты и подобное. Теперь вопрос: что из того, что нужно программам, даёт tcp/ip? Кривую абсракцию "поток байтов", с которым ебли дохуя, и всё?
@ceyt у меня должно быть понятие "соединение". Поверх любого протокола передачи битиков можно ввести это.
Конечно, в tcp/ip тоже есть такое понятие, но там соединения кривые, автоматические реконнекты не поддерживаются, например. В том числе потому и удивляюсь в посте.
@gds Совершенно нормальные там соединения, с очерёдностью пакетов, восстановлением потерянных данных и согласованием скорости передачи. Они работают с каждым посланным пакетом, а разрыв связи на минуту, исчезновение интерфейса и прочие проблемы более высокого уровня происходят на порядки реже и требуют осмысленной реакции, а не тупого бесконечного переподключения, поэтому ты их видишь.
@ceyt типично требуется переподключение, а tcp/ip не восстанавливает потерянные данные при этом. Абсракция низкоуровневая: вроде обещают не терять данные, но при использовании в реальных условиях таки теряют. Хуже того, не начнёшь же ты слать байтики с того момента, как send вернул ошибку -- надо вводить в программу понятие "пакет", так как на tcp/ip тут положиться нельзя.
@gds Что значит «типично»? «С этого дня все программы не возвращают ошибок, а пытаются соединиться до бесконечности даже в самых невозможных конфигурациях?»
Если ты хочешь стриминг, TCP не нужен. Если ты пользуешься TCP, пользуйся понятием «TCP-соединения» и его состояния, а не «потока».
@ceyt сама по себе удача или неудача установки/восстановления соединения ничего не означает, по крайней мере в tcp/ip. До бесконечности тоже не надо -- для каждой ситуации нужны свои умолчания. Где-то можно минуту подождать, пока сообщение пройдёт и будет получен ответ, где-то пару секунд уже много. Ведь главное, для чего нужны сетевые соединения -- передача данных между хостами. Если передачи (и подтверждений на переданные данные) нет какое-то время -- ошибка, на неё нужна реакция. А если send() вернул ошибку -- это ещё ничего не означает, и надо пробовать дальше, пока не станет ясно, что передачи данных так и не будет. А это можно определить только по времени. Какое-нибудь connection refused это не показатель тоже.
я придумал, где нужен поток байтов! Берём какую-нибудь телеметрию, датчик выдаёт 256 различных показаний (редкий случай, согласен). И это гоним по tcp/ip.
Только обычно данные нужны вовремя, поэтому ставим TCP_NODELAY. И считаем оверхед.
@gds Ну блин, представь применение TCP в те стародавние времена, когда приложениям назначались стандартные порты. Есть клиент, есть сервер, они устанавливают соединение, запрос-ответ, соединение закрывается. Если произошла ошибка — значит, произошла ошибка. Если надо опять связаться — открывается новый сеанс. В рамках такого представления TCP всё правильно делает: обеспечивает целостность, восстанавливается после краковременных разрывов (потерь пакетов), подерживает соединение, пока программа долго думает над ответом, автоматически регулирует скорость передачи (например, если принимающей стороне не хватает производительности обработать целый мегабит в секунду). Это сейчас всюду pipelining, P2P и прочая хрень, и в роутерах не хватает памяти на таблицу соединений, а тогда экстенсивный вариант вполне работал.
Если нужны мультиплексирование или сохранение состояния между сеансами, можно либо написать протокол поверх TCP (тысячи их, и всем известны), либо взять простой UDP, и реализовать то, что хочется, так, как хочется.
@gds tcp/ip это стек во-первых, который в принципе обеспечивает сеть, ты сейчас говоришь об уровне 3. Что даёт tcp/ip - единый интерфейс, спецификации, которых придерживаются все, какой бы ты не купил роутер, он будет работать, например. Юзай raw ip socket, в чём проблема? Вон tox'я юзает сырой udp. Какая вообще задача у тебя или это пердёж в пустоту?
@ceyt про стародавние времена понятно, им tcp/ip казался просто охуенным, но чисто по контрасту с остальным. Они, видимо, думали, что поток байтов -- это такая охуенная абстракция, и всё есть смысл загонять в неё.
@je tcp/ip даёт хуёвый единый интерфейс. Такой интерфейс никому не нужен.
Задача у меня -- надёжная передача сообщений поверх tcp/ip. Точнее, поверх вебсокетов, я взял именно их для фрейминга. С технической точки зрения всё просто, мне вот идеологически не нравится ваще: я делаю свои подтверждения доставки поверх фрейминга, внесённого искусственно в поток байтов (изначально не нужен поток байтов), и поверх подтверждений уровня tcp/ip (изначально не нужны подтверждения на потоках байтов, если есть подтверждения на уровне сообщений).
@gds А, ну да, неплохо было бы. Первое, вроде, особо в протокол не обязательно всовывать (какая разница протоколу между коннектом и реконнектом), а вот подтверждение можно запилить сразу.
@gds Ну оно-то понятно, я имею в виду что сделать это библиотекой, своим кодом или протоколом -- скорее всего один хер будет. По шнурку всё равно одинаковые данные побегут, потому в протокол пихать особого смысла нету, разве что вынести ещё больше логики на сетевую карту (и память).
@kb Ну и реконнекты -- дело часто специфическое, у нас, например -- часто при реконнекте надо выбрать другое место куда писать, а бывает нужно лимит по кол-ву попыток, бывает ещё как-то.
@kb хер не один. tcp/ip-шное говно добавляет оверхед по трафику (и добавляет лишнюю абстракцию, которую все забарывают своим фреймингом, потому что в реальных делах поток байтов не нужен).
По шнурку -- одинаково, но плюс-минус заголовки.
Про сетевую карту -- не будет там особой логики, поверх того же ip можно было бы сделать протокол.
А память -- хз, вот лично мне надо что-то думать про очень большие сообщения. Мелочь-то можно в тот же tcp-шный 128kb-буфер положить, будет вполне ок.
@kb про "другое место" -- логично таки. Но это должен быть как бы хинт, а не то, на что завязана вся логика. Хинт вида "хост скорее всего недоступен, но пока неизвестно точно".
Лимит по количеству попыток -- бредота, хотя это реализовать проще всего. Единственный разумный лимит -- по времени, за которое не получилось совершить передачу данных (с подтверждением этой передачи).
Но и тут надо подумать -- гигабайтный пакетик будет долго кидаться, а делать таймаут зависимым от объёма данных -- криво. Так как мне всяко надо будет об этом думать и это делать, может подкинешь идей? Как текущий вариант -- получатель в случае больших пакетов будет отправлять сообщения типа "получено 1Мб", "получено 2Мб" .., чтобы было понятно, идут данные или нет.
ОП, ну-ка поясни за ненужность абстракции потока байтиков. Ты говоришь, что приложениям это не нужно, им нужны якобы свои пакетики на своем уровне. ОК, но если я хочу просто передать большой непрозрачный блоб вроде файла? Станешь говорить, что мой фтп-сервер просто шлёт n-гигабайтный пакет? лел
@ulidtko хули ты тут развыебывался, специалист по байтикам штоль? тебе сказали ненужно, так заткни варежку и иди боинхи сбивать, хохол-специалист, хе-хе
@ulidtko вариант 1: в фтп-сервере будет 1. либо явная разбивка файла на сообщения, 2. либо указание "я ещё не дослал своё сообщение, но пока так отправь".
Вариант 2: да, гигабайтное сообщение, который отправляется из известного "генератора" (например, из функции, возвращающей последовательные куски файла; суть в том, что не из памяти), и принимается+обрабатывается тоже потоковым образом, например, итератами или чем-то подобным.
Но надо определять, где проводить границы надёжности доставки. Я таки хочу на уровне сообщений, поэтому большие пакеты явно не ок, и скорее всего будет вариант 1 для примера с фтп.
@krkm сообщение -- информация, которой обмениваются программы. Очевидно, сообщение может быть [де]сериализовано. Сообщение можно отправить одной программой и принять другой. Для тупых можно считать сообщение набором битиков.
@gds Почему лимит по кол-ву попыток бред? Ну у меня лично задача такая: есть кластер редисов, при записи "в случайный" выбираю этот самый случайный и пишу в него, пробую 5 раз. Если 5 раз не записалось (таймаут там, или ещё какая ошибка сети) -- значит я его из кластера временно вынимаю. Потом другой воркер занимается попыткой подключить время от времени отключённых.
Возможно таймаут имеется в виду таймаут подтверждения, что "сообщение получено". Короче, ничего не подскажу, т.к. не специалист нихуя, и обсуждать тут тяжело т.к. каждый о своём.
@gds Я говорю о том, что протокол -- это описание того, что идёт по шнурку. А логика "если сообщение не подтверждено -- повторить отправку" к этому иметь отношения не будет. Будет только если будет предусмотрен флаг "попытка №".
@ulidtko Насколько я понял, имеется в виду немного другое. Каждый лепит свой собственный формат "сообщений", или Паскале-подобный или Си-подобные, или ещё какие, но суть одна -- поток байтов (tcp в текущем его виде) использовать для приложений без придумывания велосипедов невозможно, т.к. ты не знаешь, сколько байт ты должен получить и когда остановиться читать.
@kb это-то понятно. Ясен хуй, что для простой коммуникации на седьмом уровне (типа чатиков, например), строить application protocol проще на датаграммных гарантиях, чем на стримовых.
вопрос ведь в другом: все равно остаются приложения, где стримовые гарантии более удобны, чем датаграммные. А гдс задвигает, что якобы нет.
----
алсо спалите годный датаграммный транспортный протокол (вроде udp, только с секвенированием, реордером и ресендами, и с гарантиями на границах юзерских датаграмм (а не где угодно внутри))
@kb > Почему лимит по кол-ву попыток бред?
В общем случае потому, что попытка, если она без таймаута, может затянуться надолго. Если же есть таймаут, то лимит по попыткам не так уж плох.
Но может быть так, что какие-то попытки провалились из-за сети, какие-то из-за редиса, и все их мешать в кучу -- если тебе норм, то ок, конечно.
@ulidtko > остаются приложения, где стримовые гарантии более удобны, чем датаграммные
всё равно там поток не из байтиков, а из каких-то "сообщений". Если ошибаюсь -- интересны примеры.
@gds Да, таймаут должен быть, безусловно.
Ну, в случае общения с абстрактным элементом кластера мне, конечно, пофигу кто виноват -- если плохо работает то надо выключать. Но в целом ответ об ошибке редиса от ошибки сети отличается, конечно.