Вроде задача типовая и решения очевидно , но хотелось бы узнать как тут принято делать
Надо скажем по сети передать кусок данных заведомо больший чем один tcp пакет
как на стороне приема правильно принять в том плане что у меня там идет прием пакаетов и мне надо как-то знать после приема первого надо ждат второй или это все данные.
Вроде можно при передаче конечно вначале длинну всего передаваемого пакета высылать и на приеме ее чухать и по ней ориентироватцо, но может есть какие-то другие общеизвестные приемы?
Входить в цикл и выгребать пока выгребается тоже как-то не очень ибо когда ничего нет , то непонятно, то ли по таймауту завершаем цикл приема ибо это все данные, то ли просто кто-то где-то споткнулся о кабель/образовался шторм в сети/еще какая неразбериха (а у нас в конторе к сожалению такое бывает из-за вечных экспериментов) и мы прсото не получили все что там надо за разумный промежуок времени.
Re: Как организовать корректный прием блочных данных по соке
Здравствуйте, V-ctor, Вы писали:
VC>Вроде можно при передаче конечно вначале длинну всего передаваемого пакета высылать и на приеме ее чухать и по ней ориентироватцо, но может есть какие-то другие общеизвестные приемы?
Например:
— использовать разделители между пакетами;
— складировать вообще всё принятое и только потом парсить, пытаясь разобрать пакет.
...coding for chaos...
Re: Как организовать корректный прием блочных данных по соке
Здравствуйте, V-ctor, Вы писали:
VC>Вроде задача типовая и решения очевидно , но хотелось бы узнать как тут принято делать
VC>Надо скажем по сети передать кусок данных заведомо больший чем один tcp пакет VC>как на стороне приема правильно принять в том плане что у меня там идет прием пакаетов и мне надо как-то знать после приема первого надо ждат второй или это все данные.
"пакетов" в tcp для юзверя не существует
VC>Вроде можно при передаче конечно вначале длинну всего передаваемого пакета высылать и на приеме ее чухать и по ней ориентироватцо, но может есть какие-то другие общеизвестные приемы?
если TCP это поток с терминатором, то тут думать нечего...
VC>Входить в цикл и выгребать пока выгребается тоже как-то не очень ибо когда ничего нет , то непонятно, то ли по таймауту завершаем цикл приема ибо это все данные, то ли просто кто-то где-то споткнулся о кабель/образовался шторм в сети/еще какая неразбериха (а у нас в конторе к сожалению такое бывает из-за вечных экспериментов) и мы прсото не получили все что там надо за разумный промежуок времени.
можно ожидать терминатора('/0'), но лучше не изобретать велосипед, а посмотреть на готовые протоколы, где такое уже реализовано(HTTP), да и еще и со всякими фичами...
Re: Как организовать корректный прием блочных данных по соке
Здравствуйте, V-ctor, Вы писали:
VC>Вроде задача типовая и решения очевидно , но хотелось бы узнать как тут принято делать
VC>Надо скажем по сети передать кусок данных заведомо больший чем один tcp пакет VC>как на стороне приема правильно принять в том плане что у меня там идет прием пакаетов и мне надо как-то знать после приема первого надо ждат второй или это все данные.
VC>Вроде можно при передаче конечно вначале длинну всего передаваемого пакета высылать и на приеме ее чухать и по ней ориентироватцо, но может есть какие-то другие общеизвестные приемы?
VC>Входить в цикл и выгребать пока выгребается тоже как-то не очень ибо когда ничего нет , то непонятно, то ли по таймауту завершаем цикл приема ибо это все данные, то ли просто кто-то где-то споткнулся о кабель/образовался шторм в сети/еще какая неразбериха (а у нас в конторе к сожалению такое бывает из-за вечных экспериментов) и мы прсото не получили все что там надо за разумный промежуок времени.
Можно использовать сигнальный байт как конец посылки. Если в посылке встречается байт такой же как и сигнальный, записываем за ним сигнальный байт.
Концом посылки будет нечётный подряд идущий сигнальный байт(точнее то что перед ним)Естественно данные придётся чистить от лишних сигнальных байт.
Указывать длину посылки проще.
Программа — мысли спрессованные в код.
Re: Как организовать корректный прием блочных данных по соке
Здравствуйте, V-ctor, Вы писали:
VC>Вроде задача типовая и решения очевидно , но хотелось бы узнать как тут принято делать
Принято сначала втыкать заголовок фиксированной длины, где задаётся версия заголовка, размер последующего блока и т.п. Кроме непосредственной пользы при приёме, это даёт скрытый плюс — такие блоки данных можно оборачивать во внешний протокол, поодиночке или пачками (прецеденты встречались). Т.е. а-ля XML, только вместо обрамляющих тегов, в которые завернут inner xml, используется заголовок + длина.
Re: Как организовать корректный прием блочных данных по соке
Спасибо всем откликнувшимся. Да пожалуй передача заголовка с указанеим длинны наиболее приемлемый для меня вариант. Вообще оказывается все это хорошо освещено в книге "Эффективное программирование TCP/IP" совет 6, с примерами записи и чтения блочных данных из сокета. Может кому пригодицо. Жаль сразу не наткнулся на нее )))
Re: Как организовать корректный прием блочных данных по соке
Здравствуйте, V-ctor, Вы писали:
VC>Надо скажем по сети передать кусок данных заведомо больший чем один tcp пакет
TCP это потоковый протокол.
VC>как на стороне приема правильно принять в том плане что у меня там идет прием пакаетов и мне надо как-то знать после приема первого надо ждат второй или это все данные.
Читаешь сокет, когда прочитаешь ноль байт это и есть конец, если дующее чтение вернёт ошибку.
VC>Входить в цикл и выгребать пока выгребается тоже как-то не очень ибо когда ничего нет , то непонятно, то ли по таймауту завершаем цикл приема ибо это все данные, то ли просто кто-то где-то споткнулся о кабель/образовался шторм в сети/еще какая неразбериха (а у нас в конторе к сожалению такое бывает из-за вечных экспериментов) и мы прсото не получили все что там надо за разумный промежуок времени.
Если данные можно доставить TCP доставит, проблемы сети это не проблемы протокола. В цикле использовать select/pselect/poll/ppoll/epoll, man recvmsg — > MSG_WAITALL
Компьютер — это конечный автомат. Потоковое программирование нужно тем, кто не умеет программировать конечные автоматы (c) Алан Кокс
Re[2]: Как организовать корректный прием блочных данных по с
Здравствуйте, microcod, Вы писали:
M>Можно использовать сигнальный байт как конец посылки. Если в посылке встречается байт такой же как и сигнальный, записываем за ним сигнальный байт. M>Концом посылки будет нечётный подряд идущий сигнальный байт(точнее то что перед ним)Естественно данные придётся чистить от лишних сигнальных байт.
Вот это работать не будет. Пусть X — сигнальный байт, посылка равна AXB. По твоему методу надо передать XAXXBX. Вопрос — как определить, что после этого последнего X ничего не будет? Просто ждать? Тогда это уже метод таймаута передачи, и он или неустойчивый, или медленный.
Правильно будет не так, а завести 3 других байта (отличающихся от сигнального): начало передачи, конец передачи и литеральная передача сигнала. Например, соответственно 1, x и 0. Тогда посылка AXB будет передана: X1AXxBX0. Этот метод используется (с вариациями на тему начальных посылок) в модемных протоколах (семейство Zmodem, Hydra, V.42, LAPM...)
M>Указывать длину посылки проще.
Для TCP — да. Для другой подложки — нет, но это уже выходит за пределы треда.
The God is real, unless declared integer.
Re[3]: Как организовать корректный прием блочных данных по с
N>Правильно будет не так, а завести 3 других байта (отличающихся от сигнального): начало передачи, конец передачи и литеральная передача сигнала. Например, соответственно 1, x и 0. Тогда посылка AXB будет передана: X1AXxBX0. Этот метод используется (с вариациями на тему начальных посылок) в модемных протоколах (семейство Zmodem, Hydra, V.42, LAPM...)
Не понял, а зачем нужен отдельный маркер окончания посылки? Чем не устраивает общий маркер — начало/конец? Коррекция ошибок?
Да здравствует мыло душистое и веревка пушистая.
Re[4]: Как организовать корректный прием блочных данных по с
Здравствуйте, Vamp, Вы писали:
N>>Правильно будет не так, а завести 3 других байта (отличающихся от сигнального): начало передачи, конец передачи и литеральная передача сигнала. Например, соответственно 1, x и 0. Тогда посылка AXB будет передана: X1AXxBX0. Этот метод используется (с вариациями на тему начальных посылок) в модемных протоколах (семейство Zmodem, Hydra, V.42, LAPM...) V>Не понял, а зачем нужен отдельный маркер окончания посылки? Чем не устраивает общий маркер — начало/конец? Коррекция ошибок?
Угу. С общим маркером у тебя получается, что всё, что между маркерами, должно рассматриваться как пакет и проверяться на корректность. Это, возможно, приемлемо в контексте данного треда (в случае TCP наливается столько данных, сколько хочешь), но для каналов связи неудобно. Для них, в случае короткого пропуска передачи, гонят крайние маркеры, а длинного — специальный код "покой линии". Мне тут привычнее говорить в контексте каналов связи, да и понимается с двумя раздельными маркерами обычно проще, чем с одним на начало и конец.
The God is real, unless declared integer.
Re[2]: Как организовать корректный прием блочных данных по с
Здравствуйте, AlexCrush, Вы писали:
AC>Вообще то вариантов два — или предварительная передача длины, или маркер конца (как в HTTP — два конца строки)
В HTTP используется и то, и другое