![]() |
Здравствуйте, гость ( Вход | Регистрация )
![]() |
Andrewshkovskii |
![]()
Сообщение
#1
|
Активный участник ![]() ![]() ![]() Группа: Участник Сообщений: 351 Регистрация: 27.12.2008 Пользователь №: 467 Спасибо сказали: 18 раз(а) Репутация: ![]() ![]() ![]() |
Есть клиент и сервер. Постоянно обмениваются сообщениями разной длинны.
Сейчас, что бы понять, где кончается одно сообщение и начинается другое, используется конвенция сообщений такая : Цитата %длина_всего_соообщения%|%тело сообщения% Но с этим иногда бывают косяки. Есть ли какие-то ещё конвенции или парадигмы, как лучше общаться сокетам большими сообщениями? |
|
|
![]() |
sidsukana |
![]()
Сообщение
#2
|
Участник ![]() ![]() Группа: Участник Сообщений: 158 Регистрация: 23.12.2010 Из: Челябинск Пользователь №: 2296 Спасибо сказали: 10 раз(а) Репутация: ![]() ![]() ![]() |
А чем тебя не устраивает обмениваться структурами?
Если у тебя клиент и сервер знают
Это конечно грубо я написал. В идеале лучше создать экземпляр сериализатора данных и через него записывать в сокет и из него же получать. Сообщение отредактировал sidsukana - 8.12.2011, 11:21 |
|
|
kuzulis |
![]()
Сообщение
#3
|
Активный участник ![]() ![]() ![]() Группа: Участник Сообщений: 393 Регистрация: 29.6.2009 Пользователь №: 862 Спасибо сказали: 36 раз(а) Репутация: ![]() ![]() ![]() |
Цитата Есть ли какие-то ещё конвенции или парадигмы, как лучше общаться сокетам большими сообщениями? man это и это Обычно "парадигмы" это запрос/ответ или посылка/подтверждение. Структуры кадров в общем случае выглядят: <header><body><trailer> Где header, body, trailer - это поля кадра. в header, например, могут указываться маркёры + биты направлений + биты типа пакета (первый/не первый/последний) + номер пакета + длина последующих данных body в body собственно, данные. в trailer, например, могут указываться маркёры + CRC Если сообщение уж оч длинное, то можешь разбить свою "подпрограмму" обработки сообщений на два ISO/ISI уровня: грубо канальный + приложения. Твое приложение будет принимать готовое здоровенное сообщение из уровня приложения и писать в уровень приложения. Уровень приложения принимает от здоровенное сообщение от программы, дробит его на части, и отсылает канальному(или физическому - пофик как назовешь), который оборачивает в <header><body><trailer> и шлет в сокет с обязательным ожиданием ACK от удаленной стороны. И так до конца, пока Уровень приложения не передаст все части этого сообщения. В обратку - канальный уровень из сокета принимает кусок данных как <header><body><trailer>, проверяет header, trailer . Если все ОК, то он обрезает header, trailer, вынимает кусок body и передает его наверх в Уровень приложения. Если какая-то хрень с header, trailer, то канальный уровень перезапрашивает этот кусок. Уровень приложения принимает body от канального, и для уровня приложения этот же body будет выглядеть как <header2><body2><trailer2> оно это проверяет, извлекает body2 и накапливает эти куски в своем буфере (добавляет каждый следующий кусок). И когда Уровень приложения примет от канального <header2><body2><trailer2> с указанным в header2 флагом о том, что это последний кусок - то Уровень приложения добавляет этот кусок в свой буфер и возвращает этот буфер приложению. Этот буфер и будет сообщением. Ведь нисколечки не сложно? Правда ведь? ![]() Можешь посмотреть тут , оч познавательная статья. Можешь адаптировать для себя например протокол X-Modem или еще что нить. Это если тебе нужна надежность!!! Сообщение отредактировал kuzulis - 8.12.2011, 12:21 |
|
|
ssoft |
![]()
Сообщение
#4
|
![]() Участник ![]() ![]() Группа: Участник Сообщений: 130 Регистрация: 17.2.2010 Из: Москва Пользователь №: 1470 Спасибо сказали: 30 раз(а) Репутация: ![]() ![]() ![]() |
|
|
|
Andrewshkovskii |
![]()
Сообщение
#5
|
Активный участник ![]() ![]() ![]() Группа: Участник Сообщений: 351 Регистрация: 27.12.2008 Пользователь №: 467 Спасибо сказали: 18 раз(а) Репутация: ![]() ![]() ![]() |
Цитата Есть ли какие-то ещё конвенции или парадигмы, как лучше общаться сокетам большими сообщениями? man это и это Обычно "парадигмы" это запрос/ответ или посылка/подтверждение. Структуры кадров в общем случае выглядят: <header><body><trailer> Где header, body, trailer - это поля кадра. в header, например, могут указываться маркёры + биты направлений + биты типа пакета (первый/не первый/последний) + номер пакета + длина последующих данных body в body собственно, данные. в trailer, например, могут указываться маркёры + CRC Если сообщение уж оч длинное, то можешь разбить свою "подпрограмму" обработки сообщений на два ISO/ISI уровня: грубо канальный + приложения. Твое приложение будет принимать готовое здоровенное сообщение из уровня приложения и писать в уровень приложения. Уровень приложения принимает от здоровенное сообщение от программы, дробит его на части, и отсылает канальному(или физическому - пофик как назовешь), который оборачивает в <header><body><trailer> и шлет в сокет с обязательным ожиданием ACK от удаленной стороны. И так до конца, пока Уровень приложения не передаст все части этого сообщения. В обратку - канальный уровень из сокета принимает кусок данных как <header><body><trailer>, проверяет header, trailer . Если все ОК, то он обрезает header, trailer, вынимает кусок body и передает его наверх в Уровень приложения. Если какая-то хрень с header, trailer, то канальный уровень перезапрашивает этот кусок. Уровень приложения принимает body от канального, и для уровня приложения этот же body будет выглядеть как <header2><body2><trailer2> оно это проверяет, извлекает body2 и накапливает эти куски в своем буфере (добавляет каждый следующий кусок). И когда Уровень приложения примет от канального <header2><body2><trailer2> с указанным в header2 флагом о том, что это последний кусок - то Уровень приложения добавляет этот кусок в свой буфер и возвращает этот буфер приложению. Этот буфер и будет сообщением. Ведь нисколечки не сложно? Правда ведь? ![]() Можешь посмотреть тут , оч познавательная статья. Можешь адаптировать для себя например протокол X-Modem или еще что нить. Это если тебе нужна надежность!!! Я вроде говорил о том, что над протоколом, а не внутри. Зачем Вы мне все это написали? Я не протокол пишу, а пытаюсь понять - как лучше передавать сообщения между сокетами, что бы соблюдалась целостность при передаче данных кусками (именно так оно работает в реальности). Косяки в производителельности таких алгоритмов разбора сообщения - операции со строками в основном. |
|
|
kuzulis |
![]()
Сообщение
#6
|
Активный участник ![]() ![]() ![]() Группа: Участник Сообщений: 393 Регистрация: 29.6.2009 Пользователь №: 862 Спасибо сказали: 36 раз(а) Репутация: ![]() ![]() ![]() |
Цитата Я вроде говорил о том, что над протоколом, а не внутри. Зачем Вы мне все это написали? Я тебе и написал про "НАД". Цитата Я не протокол пишу, а пытаюсь понять - как лучше передавать сообщения между сокетами, что бы соблюдалась целостность при передаче данных кусками (именно так оно работает в реальности). Я тебе написал как. Если не понимаешь - то брось это дело. Без некоего протокола передачи - у тебя ничего не получится. Бросай в общем.. |
|
|
ssoft |
![]()
Сообщение
#7
|
![]() Участник ![]() ![]() Группа: Участник Сообщений: 130 Регистрация: 17.2.2010 Из: Москва Пользователь №: 1470 Спасибо сказали: 30 раз(а) Репутация: ![]() ![]() ![]() |
Косяки в производителельности таких алгоритмов разбора сообщения - операции со строками в основном. Здесь есть пример сборки сообщения из сокета. сборка сообщения Никаких операций со строками производить не нужно. С одной стороны отправил QByteArray, с другой получил. |
|
|
Andrewshkovskii |
![]()
Сообщение
#8
|
Активный участник ![]() ![]() ![]() Группа: Участник Сообщений: 351 Регистрация: 27.12.2008 Пользователь №: 467 Спасибо сказали: 18 раз(а) Репутация: ![]() ![]() ![]() |
Цитата Я вроде говорил о том, что над протоколом, а не внутри. Зачем Вы мне все это написали? Я тебе и написал про "НАД". Цитата Я не протокол пишу, а пытаюсь понять - как лучше передавать сообщения между сокетами, что бы соблюдалась целостность при передаче данных кусками (именно так оно работает в реальности). Я тебе написал как. Если не понимаешь - то брось это дело. Без некоего протокола передачи - у тебя ничего не получится. Бросай в общем.. Не брошу. Косяки в производителельности таких алгоритмов разбора сообщения - операции со строками в основном. Здесь есть пример сборки сообщения из сокета. сборка сообщения Никаких операций со строками производить не нужно. С одной стороны отправил QByteArray, с другой получил. Дело в том, что я все это для питона собираю - там я использую строки и сериализованный json, а не bytearray. Кстати, вот код, если кому интересно :
Сообщение отредактировал Andrewshkovskii - 8.12.2011, 19:08 |
|
|
Влад |
![]()
Сообщение
#9
|
Участник ![]() ![]() Группа: Участник Сообщений: 146 Регистрация: 20.3.2009 Из: Санкт-Петербург Пользователь №: 627 Спасибо сказали: 46 раз(а) Репутация: ![]() ![]() ![]() |
|
|
|
Andrewshkovskii |
![]()
Сообщение
#10
|
Активный участник ![]() ![]() ![]() Группа: Участник Сообщений: 351 Регистрация: 27.12.2008 Пользователь №: 467 Спасибо сказали: 18 раз(а) Репутация: ![]() ![]() ![]() |
Но с этим иногда бывают косяки. Есть ли какие-то ещё конвенции или парадигмы, как лучше общаться сокетам большими сообщениями? А какой протокол используется у тебя на транспортном уровне? TCP. В общем, косяк был в алгоритме , я его переписал. Пока всё ок , но есть проблемы, когда пакеты теряются. Тогда, конечно, алгоритму беда. Сообщение отредактировал Andrewshkovskii - 14.12.2011, 23:01 |
|
|
Влад |
![]()
Сообщение
#11
|
Участник ![]() ![]() Группа: Участник Сообщений: 146 Регистрация: 20.3.2009 Из: Санкт-Петербург Пользователь №: 627 Спасибо сказали: 46 раз(а) Репутация: ![]() ![]() ![]() |
Гмм. Что-то это из категории загадок.... :-)
Во-первых, в TCP нет никаких "пакетов" - т.к. это потоковый протокол передачи данных. Во-вторых, крайне удивительно, что "пакеты теряются" - т.к. это протокол с гарантированной доставкой. Думаю, что нужно заниматься поиском багов в прикладном уровне. |
|
|
Andrewshkovskii |
![]()
Сообщение
#12
|
Активный участник ![]() ![]() ![]() Группа: Участник Сообщений: 351 Регистрация: 27.12.2008 Пользователь №: 467 Спасибо сказали: 18 раз(а) Репутация: ![]() ![]() ![]() |
Гмм. Что-то это из категории загадок.... :-) Во-первых, в TCP нет никаких "пакетов" - т.к. это потоковый протокол передачи данных. Во-вторых, крайне удивительно, что "пакеты теряются" - т.к. это протокол с гарантированной доставкой. Думаю, что нужно заниматься поиском багов в прикладном уровне. А поток из чего состоит? Т.е. Вы утверждаете, что используя TCP/IP протокол - вы никогда не потеряете фрейм с данными?Никогда-никогда? Ни при каких условиях? Вся это гарантированная доставка для сферического коня в вакууме. Не забывайте оборудование - которое может сбоить, кабеля повреждаться и т.п.. И в догонку: Цитата TCP обеспечивает надёжную непрерывную передачу данных, исключающую потерю данных или нарушение порядка их поступления или дублирования, может перераспределять данные, разбивая большие порции данных на фрагменты и наоборот склеивая фрагменты в один пакет. Ок, я не правильно назвал пакеты - порциями, тут я не прав. Суть была в том, что порция данных может потеряться, тупо оборудование засбоит и всё - не получите вы свой кусочек. Или какой-нибудь софт, вроде FW заблочит. |
|
|
BRE |
![]()
Сообщение
#13
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 1112 Регистрация: 6.3.2009 Из: Ростов-на-Дону Пользователь №: 591 Спасибо сказали: 264 раз(а) Репутация: ![]() ![]() ![]() |
Суть была в том, что порция данных может потеряться, тупо оборудование засбоит и всё - не получите вы свой кусочек. Или какой-нибудь софт, вроде FW заблочит. Нет, порция потеряться не может. Стек контролирует порядок получения пакетов и если необходимо, будет запрашивать пакет заново. Пока он этот пакет не получит, дальше он ничего отдавать не будет. Программа никогда не получит данные из сокета с "дыркой" посредине. |
|
|
Andrewshkovskii |
![]()
Сообщение
#14
|
Активный участник ![]() ![]() ![]() Группа: Участник Сообщений: 351 Регистрация: 27.12.2008 Пользователь №: 467 Спасибо сказали: 18 раз(а) Репутация: ![]() ![]() ![]() |
Т.е. , если я передаю файл, скажем, 1 гб, и где-то оборудование сдохнет - я не получу ни байта от этого потока?
Я так понимаю, я получу всё до момента сбоя - а это уже фейл и провал для предложенного алгоритма. |
|
|
BRE |
![]()
Сообщение
#15
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 1112 Регистрация: 6.3.2009 Из: Ростов-на-Дону Пользователь №: 591 Спасибо сказали: 264 раз(а) Репутация: ![]() ![]() ![]() |
Если пакет теряется - стек будет просить его перепослать. Если при этом удаленная машина перестанет отвечать, то ты получишь ошибку.
|
|
|
Влад |
![]()
Сообщение
#16
|
Участник ![]() ![]() Группа: Участник Сообщений: 146 Регистрация: 20.3.2009 Из: Санкт-Петербург Пользователь №: 627 Спасибо сказали: 46 раз(а) Репутация: ![]() ![]() ![]() |
А если ты эту ошибку не обрабатываешь, то это баг в логике прикладного уровня.... Логика прикладного уровня должна быть готова к тому, что TCP соединение может в любой момент разорваться по независящим от локального хоста причинам.
(С коллегой BRE я бы поспорил только в отношении терминологии: то, что он называет "пакетом", я склонен называть "сегментом данных". :-) ) |
|
|
BRE |
![]()
Сообщение
#17
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 1112 Регистрация: 6.3.2009 Из: Ростов-на-Дону Пользователь №: 591 Спасибо сказали: 264 раз(а) Репутация: ![]() ![]() ![]() |
(С коллегой BRE я бы поспорил только в отношении терминологии: то, что он называет "пакетом", я склонен называть "сегментом данных". :-) ) Со мной конечно можно поспорить, но в RFC793 так же частенько проскакивает так называемый "пакет", а с ним (с RFC793) спорить сложнее. ![]() |
|
|
Andrewshkovskii |
![]()
Сообщение
#18
|
Активный участник ![]() ![]() ![]() Группа: Участник Сообщений: 351 Регистрация: 27.12.2008 Пользователь №: 467 Спасибо сказали: 18 раз(а) Репутация: ![]() ![]() ![]() |
|
|
|
![]() ![]() |
![]() |
|
Текстовая версия | Сейчас: 9.4.2025, 23:15 |