Имеется вот нейкая сетевая структура, где сервер и клиент связаны по TCP.
Межде сервером и клиентом поддерживается постоянное соединение (OS: Linux Ubuntu).
Предполагается, что эти сервер и клиент — отдельные машинки локальной сети.
Вопрос: какова максимальная длина пакета, который НЕ будет разбиваться сетью на более мелкие пакеты?
Правильно ли я понимаю, что эта длина определяется параметром MTU (когда вызываем команду ifconfig или netstat -ie в Linux)?
Вопросы:
MTU равный примерно 1.5 KBytes — это для произвольных данных?
Для текстовых данных этот показатель порядка 14 KBytes. Почему различие почти в десять раз?
ПРИМЕЧАНИЕ:
Данные насчёт показателя равного 14 KBytes (для текстовых данных) — взяты отсюда: https://tylercipriani.com/blog/2016/09/25/the-14kb-in-the-tcp-initial-window
Для общего случая — следует ориентироваться значением 1.5 KBytes.
Насколько вероятна ситуация, что поменяется порядок следования пакетов? То есть — переданный в сеть позже, появится на приёме раньше.
Вышеуказанные данные получены экспериментально.
При работе без сети (local-loopback) — просто на 127.0.0.1 — максимальная длина TCP пакета намного больше. Порядка 64 KBytes.
P.S. Конечно же, я предусмотрел на стороне приёма, накопление сегментов_пакета — восствновление исходного пакета.
Оно основано на поиске 32-х битного маркера конца пакета.
Но меня интересует вопрос — как сеть дробит пакеты TCP?
Как защититься от изменения порядка следования пакетов?
Здравствуйте, AlexGin, Вы писали:
AG>Имеется вот нейкая сетевая структура, где сервер и клиент связаны по TCP. AG>Межде сервером и клиентом поддерживается постоянное соединение (OS: Linux Ubuntu). AG>Предполагается, что эти сервер и клиент — отдельные машинки локальной сети.
AG>Вопрос: какова максимальная длина пакета, который НЕ будет разбиваться сетью на более мелкие пакеты? AG>Правильно ли я понимаю, что эта длина определяется параметром MTU (когда вызываем команду ifconfig или netstat -ie в Linux)?
MTU это размер пакета. Из них полезный payload для TCP будет, ессно, меньше (заголовки тоже требуют место).
MTU бывает разный. Всякие Cisco любят какие-то дикие размеры, типа 1200 с копейками
AG>Насколько вероятна ситуация, что поменяется порядок следования пакетов? То есть — переданный в сеть позже, появится на приёме раньше.
Если в сети возникнут какие-то перебои и пакеты потеряются, то будут посланы повторно.
Если маршрутизация может поменяться, часть пакетов пойдет другим путём, то есть вероятность смены порядка.
Только если ты работаешь с TCP на прикладном уровне, то это не твоя задача. К тебе приходит упорядоченный поток.
AG>Вышеуказанные данные получены экспериментально. AG>При работе без сети (local-loopback) — просто на 127.0.0.1 — максимальная длина TCP пакета намного больше. Порядка 64 KBytes.
На то он и фуфельный девайс.
AG>P.S. Конечно же, я предусмотрел на стороне приёма, накопление сегментов_пакета — восствновление исходного пакета. AG>Оно основано на поиске 32-х битного маркера конца пакета.
Ты пытаешься сделать собственный WireShark или что?
AG>Но меня интересует вопрос — как сеть дробит пакеты TCP? AG>Как защититься от изменения порядка следования пакетов?
Всё уже украдено придумано до вас.
_____________________
С уважением,
Stanislav V. Zudin
Но там теперь НЕ Web-клиент, а толстый клиент.
НЕ протокол HTTP идёт от сервера, а TCP (от применения UDP — я уже давно отказался).
При этом — поддерживается постоянное соединение: сервер-клиент (назовём это — клиентская сессия).
При работе сессии — от сервера к клиенту может передаваться результат вычислений (пакет данных — сериализованных — размером до 10 KBytes).
Все остальные пакеты — относительно небольшие — от 10 байт до примерно 1...3 KByte.
Пакеты в 1...3 KByte — это JSON (они следуют от клиента к серверу).
Они определяют — что должен считать алгоритм бизнесс-логики на сервере.
SVZ>MTU это размер пакета. Из них полезный payload для TCP будет, ессно, меньше (заголовки тоже требуют место). SVZ>MTU бывает разный. Всякие Cisco любят какие-то дикие размеры, типа 1200 с копейками
Это для меня НЕ страшно — клиент всё равно собирает пакет из нескольких (небольших) фрагментов.
SVZ>Если в сети возникнут какие-то перебои и пакеты потеряются, то будут посланы повторно. SVZ>Если маршрутизация может поменяться, часть пакетов пойдет другим путём, то есть вероятность смены порядка.
SVZ>Только если ты работаешь с TCP на прикладном уровне, то это не твоя задача. К тебе приходит упорядоченный поток.
+100500
Да, работаю с TCP на прикладном уровне, через QTcpSocket (Qt Network)!
Тем не менее, исходный пакет вполне себе разбивается на небольшие фрагменты (что лично меня несколько удивило).
В общем — пришлось доработать так, чтобы была сборка пакета из фрагментов.
AG>При работе без сети (local-loopback) — просто на 127.0.0.1 — максимальная длина TCP пакета намного больше. Порядка 64 KBytes.
SVZ>На то он и фуфельный девайс.
Ладно. Для межпроцессной коммуникации в одном компе — совсем даже неплохо.
SVZ>Ты пытаешься сделать собственный WireShark или что?
Что я делаю — я уже указал выше.
Ну а маркер конца пакета я ввёл для того, чтобы собрать на приёме (на клиенте) полный пакет от сервера.
Это вызвано тем, что сеть дробит пакет с результатами вычислений от сервера на небольшие фрагменты.
При этом — маркер конца пакета я формирую и добавляю сам к прикладному пакету — при формировании паета на сервере (это не то, что использовано под_капотом_протокола_TCP).
Реализация проверки пакета на маркер конца — показалась мне более логичной, чем что-либо другое.
Здравствуйте, AlexGin, Вы писали:
SVZ>>Только если ты работаешь с TCP на прикладном уровне, то это не твоя задача. К тебе приходит упорядоченный поток. AG>Да, работаю с TCP на прикладном уровне, через QTcpSocket (Qt Network)!
AG>Тем не менее, исходный пакет вполне себе разбивается на небольшие фрагменты (что лично меня несколько удивило). AG>В общем — пришлось доработать так, чтобы была сборка пакета из фрагментов.
Я подозреваю, ты немного о другой разбивке.
Т.к. это поток, то конца у него естественно нет. Только по своим признакам ты можешь определить, когда надо прекратить чтение. Либо передавать размер данных в начале, либо передавать какой-то маркер.
Размер кусков, вычитываемых за один раз из сокета, это вообще дело тёмное, отдано на откуп системе и с MTU никак не связано.
Скорость приема данных на уровне драйвера и скорость чтения прикладной программой из сокета разные, поэтому за одно чтение ты можешь зачитать сразу несколько пакетов. В общем не парься.
Максимум — ты можешь порулить размером буфера, выделяемого под сокет. В 99.9% дефолтных значений хватит за глаза.
А размер буфера в прикладной программе — полностью под твоим контролем, хоть по одному байту читай.
_____________________
С уважением,
Stanislav V. Zudin
Здравствуйте, уважаемый Stanislav V. Zudin, Вы писали:
SVZ>Я подозреваю, ты немного о другой разбивке. SVZ>Т.к. это поток, то конца у него естественно нет. Только по своим признакам ты можешь определить, когда надо прекратить чтение. Либо передавать размер данных в начале, либо передавать какой-то маркер.
Да, передавать полный размер в начале — также неплохая идея. Может стоит совместить это с маркером конца пакета? На случай потери промежуточных фрагментов, например.
SVZ>Размер кусков, вычитываемых за один раз из сокета, это вообще дело тёмное, отдано на откуп системе и с MTU никак не связано. SVZ>Скорость приема данных на уровне драйвера и скорость чтения прикладной программой из сокета разные, поэтому за одно чтение ты можешь зачитать сразу несколько пакетов.
Следующий пакет от сервера — не приходит, пока клиент не подтвердил (не квитировал) предшествующий.
SVZ>Максимум — ты можешь порулить размером буфера, выделяемого под сокет. В 99.9% дефолтных значений хватит за глаза.
А какие это значения?
SVZ>А размер буфера в прикладной программе — полностью под твоим контролем, хоть по одному байту читай.
Вот это интересно.
Где подробнее об этом почитать? Какие ключевые слова гуглить?
Ну и отдельный вопрос — возможно уже не к тебе — реализовано ли это как-то в Qt5?
Здравствуйте, AlexGin, Вы писали:
AG>Да, передавать полный размер в нвчале — также неплохая идея. Может стоит совместить это с маркером конца пакета? На случай потери промежуточных фрагментов, например.
В протоколе TCP не может быть потерянных пакетов. Восстановление последовательности выполняется на нижнем уровне.
На твоём прикладном уровне все пакеты на месте и в нужном порядке.
SVZ>>Размер кусков, вычитываемых за один раз из сокета, это вообще дело тёмное, отдано на откуп системе и с MTU никак не связано. SVZ>>Скорость приема данных на уровне драйвера и скорость чтения прикладной программой из сокета разные, поэтому за одно чтение ты можешь зачитать сразу несколько пакетов.
AG>Следующий пакет от сервера — не приходит, пока клиент не подтвердил (не квитировал) предшествующий.
Там всё немного сложнее. Подтверждаться может не каждый пакет, а целая цепочка.
SVZ>>Максимум — ты можешь порулить размером буфера, выделяемого под сокет. В 99.9% дефолтных значений хватит за глаза. SVZ>>А размер буфера в прикладной программе — полностью под твоим контролем, хоть по одному байту читай.
AG>Вот это интересно. AG>Где подробнее об этом почитать? Какие ключевые слова гуглить?
setsockopt
AG>Ну и отдельный вопрос — возможно уже не к тебе — реализовано ли это как-то в Qt5?
Какая-нибудь ручка наружу обязательно торчит.
_____________________
С уважением,
Stanislav V. Zudin
Здравствуйте, AlexGin, Вы писали:
AG>Имеется вот нейкая сетевая структура, где сервер и клиент связаны по TCP. AG>Межде сервером и клиентом поддерживается постоянное соединение (OS: Linux Ubuntu). AG>Предполагается, что эти сервер и клиент — отдельные машинки локальной сети.
AG>Вопрос: какова максимальная длина пакета, который НЕ будет разбиваться сетью на более мелкие пакеты?
TCP не оперирует пакетами. TCP это поточный протокол.
AG>Правильно ли я понимаю, что эта длина определяется параметром MTU (когда вызываем команду ifconfig или netstat -ie в Linux)?
MTU это размер IP пакета.
AG>MTU равный примерно 1.5 KBytes — это для произвольных данных? AG>Для текстовых данных этот показатель порядка 14 KBytes. Почему различие почти в десять раз?
Размер IP пакета не зависит от того, какого рода данные в него кладут. Это гораздо более низкий уровень абстракции.
AG>Насколько вероятна ситуация, что поменяется порядок следования пакетов? То есть — переданный в сеть позже, появится на приёме раньше.
Если речь об IP, то ненулевая и зависит от типа сети. Например в WiFi это обычное дело, как и пропавшие пакеты, дубликаты и тд.
AG>Но меня интересует вопрос — как сеть дробит пакеты TCP? AG>Как защититься от изменения порядка следования пакетов?
При использовании TCP обо всех проблемах заботится операционная система. Программисту про это думать нужды нет. В каком порядке байты уходят в сокет с одной стороны, в том порядке придут с другой стороны.
Здравствуйте, уважаемый Stanislav V. Zudin, Вы писали:
SVZ>В протоколе TCP не может быть потерянных пакетов. Восстановление последовательности выполняется на нижнем уровне. SVZ>На твоём прикладном уровне все пакеты на месте и в нужном порядке.
+100500
Я в курсе, что теория говорит об этом. Практика иногда может и отличаться
SVZ>Там всё немного сложнее. Подтверждаться может не каждый пакет, а целая цепочка.
На моей (прикладной) стороне — обеспечена передача квитирования в сторону сервера, когда на клиенте приняли пакет (ну или же собрали из фрагментов)
и результат визуализировали для юзера.
SVZ>Какая-нибудь ручка наружу обязательно торчит.
Может вот это самое то: QAbstractSocket::setSocketOption QAbstractSocket::SendBufferSizeSocketOption
Здравствуйте, уважаемый vsb, Вы писали:
vsb>TCP не оперирует пакетами. TCP это поточный протокол.
+100500
Да, может я и неправильно назвал данную сущность, но для моей задачи — характерны блоки данных (которые я назвал пакетами).
AG>>Правильно ли я понимаю, что эта длина определяется параметром MTU (когда вызываем команду ifconfig или netstat -ie в Linux)?
vsb>MTU это размер IP пакета.
То есть — для уровня TCP, это значение может оказаться лишённое смысла...
AG>>MTU равный примерно 1.5 KBytes — это для произвольных данных? AG>>Для текстовых данных этот показатель порядка 14 KBytes. Почему различие почти в десять раз?
vsb>Размер IP пакета не зависит от того, какого рода данные в него кладут. Это гораздо более низкий уровень абстракции.
Эту теорию я знаю уже не первый год. Вот почему же на практике иначе?
AG>>Насколько вероятна ситуация, что поменяется порядок следования пакетов? То есть — переданный в сеть позже, появится на приёме раньше.
vsb>Если речь об IP, то ненулевая и зависит от типа сети. Например в WiFi это обычное дело, как и пропавшие пакеты, дубликаты и тд
Вот это уже теплее!
vsb>При использовании TCP обо всех проблемах заботится операционная система. Программисту про это думать нужды нет.
Это только в теории...
Впрочем, я также думал до недавнего времени. Пока не столкнулся с ситуацией:
Когда сервер и клиент — на одном и том же компе — всё работает как швейцарские часы.
Но вот если сервер и клиент — соединены проводом и через хаб — как это в реальной жизни — то тут начинается практика...
Здравствуйте, AlexGin, Вы писали:
AG>Вопрос: какова максимальная длина пакета, который НЕ будет разбиваться сетью на более мелкие пакеты? AG>Правильно ли я понимаю, что эта длина определяется параметром MTU (когда вызываем команду ifconfig или netstat -ie в Linux)?
MTU — это параметр сетевого интерфейса, который определяет максимальный размер пакета (все равно какого, TCP, UDP, ICMP...), который не будет фрагментироваться при отправке через этот интерфейс.
TCP, естественно, не хочет, чтобы его пакеты фрагментировались. Поэтому при соединении по локальной сети TCP будет ориентироваться на MTU, за вычетом служебных данных. А вот если соединение нелокальное, то у TCP нет знаний о том, как будет происходить фрагментация на промежуточных узках. Поэтому он будет исходить из максимального размера пакета, доставка которого без фрагментации гарантируется IP-протоколом. А это 576 байт для IPv4, и 1280 для IPv6.
AG>MTU равный примерно 1.5 KBytes — это для произвольных данных? AG>Для текстовых данных этот показатель порядка 14 KBytes. Почему различие почти в десять раз?
Нет никакого различия. MTU не зависит от данных.
AG>Насколько вероятна ситуация, что поменяется порядок следования пакетов? То есть — переданный в сеть позже, появится на приёме раньше.
Около 1% пакетов, если мы говорим о "большом интернете".
AG>Но меня интересует вопрос — как сеть дробит пакеты TCP? AG>Как защититься от изменения порядка следования пакетов?
Здравствуйте, AlexGin, Вы писали:
AG>При работе сессии — от сервера к клиенту может передаваться результат вычислений (пакет данных — сериализованных — размером до 10 KBytes). AG>Все остальные пакеты — относительно небольшие — от 10 байт до примерно 1...3 KByte. AG>Пакеты в 1...3 KByte — это JSON (они следуют от клиента к серверу). AG>Они определяют — что должен считать алгоритм бизнесс-логики на сервере.
Термин "пакет" в контексте разговоров о сети несколько перегружен. Я бы использовал "блок" или что-нибудь в этом роде.
AG>Тем не менее, исходный пакет вполне себе разбивается на небольшие фрагменты (что лично меня несколько удивило). AG>В общем — пришлось доработать так, чтобы была сборка пакета из фрагментов.
TCP, логически — это поток байтов. И когда ты отправляешь, скажем, 10 килобайт, то прийти они могут одним куском, а могут произвольным количеством кусков. Но в любом случае, они придут в том же порядке, в котором были отправлены.
Если тебе нужно, логически, пересылать данные блоками, с сохранением границ блоков, то надо предусмотреть какой-то свой механизм. Например, перед каждым блоком передается его длинна.
Здравствуйте, AlexGin, Вы писали:
AG>Здравствуйте, уважаемый vsb, Вы писали:
vsb>>TCP не оперирует пакетами. TCP это поточный протокол. AG>+100500 AG>Да, может я и неправильно назвал данную сущность, но для моей задачи — характерны блоки данных (которые я назвал пакетами).
Я бы не советовал смешивать пакеты на уровне протокола и пакеты на уровне IP. Да, если пишешь 500 байтов в сокет и больше ничего не делаешь, то скорей всего они так и приедут в одном IP-пакете (с прицепленными TCP и IP заголовками). Но на "скорее всего" полагаться нельзя. В общем случае это сущности разные. Может и в одном IP пакете быть куча пакетов протокола. Может быть и наоборот.
AG>>>Правильно ли я понимаю, что эта длина определяется параметром MTU (когда вызываем команду ifconfig или netstat -ie в Linux)?
vsb>>MTU это размер IP пакета. AG>То есть — для уровня TCP, это значение может оказаться лишённое смысла...
Ну с ним мало что можно сделать, с этим значением. Преобразованием потока байтов в IP пакеты занимается операционная система, приложение тут ни на что влиять не может.
AG>>>MTU равный примерно 1.5 KBytes — это для произвольных данных? AG>>>Для текстовых данных этот показатель порядка 14 KBytes. Почему различие почти в десять раз?
vsb>>Размер IP пакета не зависит от того, какого рода данные в него кладут. Это гораздо более низкий уровень абстракции. AG> AG>Эту теорию я знаю уже не первый год. Вот почему же на практике иначе?
Что именно на практике иначе, я не совсем понимаю? Как меряете?
vsb>>При использовании TCP обо всех проблемах заботится операционная система. Программисту про это думать нужды нет.
AG>Это только в теории... AG>Впрочем, я также думал до недавнего времени. Пока не столкнулся с ситуацией: AG>Когда сервер и клиент — на одном и том же компе — всё работает как швейцарские часы. AG>Но вот если сервер и клиент — соединены проводом и через хаб — как это в реальной жизни — то тут начинается практика...
На практике в TCP протоколе может рваться соединение, потому, что какая-нибудь дурацкая коробка посредине так решила. Чтобы в TCP-протоколе терялись байты или приходили не в том порядке — такого быть не может. Ну т.е. понятно, что если коробка посредине зловредная, то всё может быть, но обычно в реальной жизни зловредных коробок нет. И скорей всего баг в вашем коде, который не проявляется при очень быстрой сети (на локалхосте скорость практически бесконечная) и проявляется в реальной сети. Например частая ошибка — люди всё же трактуют TCP как пакетный протокол, хоть он и поточный. Думают, что если записали в него тысячу байтов, то на другом конце чтение вернёт все эти тысячу байтов. А не факт. Оно может возвращать тысячу раз по одному байту. Т.е. понятно, что в конечном счёте все байты придут и прочитаются, но вот именно read совершенно не обязан читать весь пакет целиком. Это я пытаюсь играть в оракула по косвенным данным определяя баг (: Может быть даже угадаю.
Здравствуйте, AlexGin, Вы писали:
AG>Да, передавать полный размер в начале — также неплохая идея. Может стоит совместить это с маркером конца пакета? На случай потери промежуточных фрагментов, например.
Здравствуйте, Pzz, Вы писали:
Pzz>Здравствуйте, AlexGin, Вы писали:
AG>>Я в курсе, что теория говорит об этом. Практика иногда может и отличаться
Pzz>Нет, не может. А твои слишком умные защиты замаскируют твои собственные ошибки, приводящие к потере данных.
может на практике когда сильно умные DPI или оборудование у прова которое не выдерживает транзита
если не сильно большой pps и не сильно заумный траффик
тогда можно не волноваться
Здравствуйте, уважаем ый Pzz, Вы писали:
Pzz>Нет, не может. А твои слишком умные защиты замаскируют твои собственные ошибки, приводящие к потере данных.
+100500
Вот чтобы этого избежать — я и создал данную тему!
Здравствуйте, reversecode, Вы писали:
R>может на практике когда сильно умные DPI или оборудование у прова которое не выдерживает транзита R>если не сильно большой pps и не сильно заумный траффик R>тогда можно не волноваться
Здравствуйте, уважаемый Pzz, Вы писали:
Pzz>Термин "пакет" в контексте разговоров о сети несколько перегружен. Я бы использовал "блок" или что-нибудь в этом роде.
Ну пусть "блок" — кому легче/теплее
Pzz>TCP, логически — это поток байтов. И когда ты отправляешь, скажем, 10 килобайт, то прийти они могут одним куском, а могут произвольным количеством кусков. Но в любом случае, они придут в том же порядке, в котором были отправлены.
+100500
Вот это уже хорошо!!! Это отлично!
Pzz>Если тебе нужно, логически, пересылать данные блоками, с сохранением границ блоков, то надо предусмотреть какой-то свой механизм. Например, перед каждым блоком передается его длинна.
+100500
Хорошо, если я буду ориентироваться на длину, мне убирать мой_собственный маркер конца блока,
или же оставить, как дополнительную проверку валидности?
Здравствуйте, уважаемый reversecode, Вы писали:
R>может на практике когда сильно умные DPI или оборудование у прова...
Нет, это не тот случай — здесь нет ISP.
Здравствуйте, AlexGin, Вы писали:
Pzz>>Термин "пакет" в контексте разговоров о сети несколько перегружен. Я бы использовал "блок" или что-нибудь в этом роде. AG>Ну пусть "блок" — кому легче/теплее
Мне легче и теплее.
AG>+100500 AG>Хорошо, если я буду ориентироваться на длину, мне убирать мой_собственный маркер конца блока, AG>или же оставить, как дополнительную проверку валидности?
Что-то одно из двух убрать, или длину, или маркер конца. С длиной приемник будет эффективнее работать: не надо будет сканировать каждый байт в поисках маркера.