Как организовать корректный прием блочных данных по сокету?
От: V-ctor  
Дата: 02.09.10 07:38
Оценка:
Вроде задача типовая и решения очевидно , но хотелось бы узнать как тут принято делать

Надо скажем по сети передать кусок данных заведомо больший чем один tcp пакет
как на стороне приема правильно принять в том плане что у меня там идет прием пакаетов и мне надо как-то знать после приема первого надо ждат второй или это все данные.

Вроде можно при передаче конечно вначале длинну всего передаваемого пакета высылать и на приеме ее чухать и по ней ориентироватцо, но может есть какие-то другие общеизвестные приемы?

Входить в цикл и выгребать пока выгребается тоже как-то не очень ибо когда ничего нет , то непонятно, то ли по таймауту завершаем цикл приема ибо это все данные, то ли просто кто-то где-то споткнулся о кабель/образовался шторм в сети/еще какая неразбериха (а у нас в конторе к сожалению такое бывает из-за вечных экспериментов) и мы прсото не получили все что там надо за разумный промежуок времени.
Re: Как организовать корректный прием блочных данных по соке
От: neFormal Россия  
Дата: 02.09.10 07:39
Оценка:
Здравствуйте, V-ctor, Вы писали:

VC>Вроде можно при передаче конечно вначале длинну всего передаваемого пакета высылать и на приеме ее чухать и по ней ориентироватцо, но может есть какие-то другие общеизвестные приемы?


Например:
— использовать разделители между пакетами;
— складировать вообще всё принятое и только потом парсить, пытаясь разобрать пакет.
...coding for chaos...
Re: Как организовать корректный прием блочных данных по соке
От: AlexCrush Россия  
Дата: 02.09.10 07:40
Оценка:
Вообще то вариантов два — или предварительная передача длины, или маркер конца (как в HTTP — два конца строки)
Re: Как организовать корректный прием блочных данных по соке
От: Viper_Craft  
Дата: 02.09.10 07:44
Оценка:
Здравствуйте, V-ctor, Вы писали:

VC>Вроде задача типовая и решения очевидно , но хотелось бы узнать как тут принято делать


VC>Надо скажем по сети передать кусок данных заведомо больший чем один tcp пакет

VC>как на стороне приема правильно принять в том плане что у меня там идет прием пакаетов и мне надо как-то знать после приема первого надо ждат второй или это все данные.

"пакетов" в tcp для юзверя не существует

VC>Вроде можно при передаче конечно вначале длинну всего передаваемого пакета высылать и на приеме ее чухать и по ней ориентироватцо, но может есть какие-то другие общеизвестные приемы?


если TCP это поток с терминатором, то тут думать нечего...

VC>Входить в цикл и выгребать пока выгребается тоже как-то не очень ибо когда ничего нет , то непонятно, то ли по таймауту завершаем цикл приема ибо это все данные, то ли просто кто-то где-то споткнулся о кабель/образовался шторм в сети/еще какая неразбериха (а у нас в конторе к сожалению такое бывает из-за вечных экспериментов) и мы прсото не получили все что там надо за разумный промежуок времени.


можно ожидать терминатора('/0'), но лучше не изобретать велосипед, а посмотреть на готовые протоколы, где такое уже реализовано(HTTP), да и еще и со всякими фичами...
Re: Как организовать корректный прием блочных данных по соке
От: microcod США www.tehnoromantik.net
Дата: 02.09.10 07:58
Оценка:
Здравствуйте, V-ctor, Вы писали:

VC>Вроде задача типовая и решения очевидно , но хотелось бы узнать как тут принято делать


VC>Надо скажем по сети передать кусок данных заведомо больший чем один tcp пакет

VC>как на стороне приема правильно принять в том плане что у меня там идет прием пакаетов и мне надо как-то знать после приема первого надо ждат второй или это все данные.

VC>Вроде можно при передаче конечно вначале длинну всего передаваемого пакета высылать и на приеме ее чухать и по ней ориентироватцо, но может есть какие-то другие общеизвестные приемы?


VC>Входить в цикл и выгребать пока выгребается тоже как-то не очень ибо когда ничего нет , то непонятно, то ли по таймауту завершаем цикл приема ибо это все данные, то ли просто кто-то где-то споткнулся о кабель/образовался шторм в сети/еще какая неразбериха (а у нас в конторе к сожалению такое бывает из-за вечных экспериментов) и мы прсото не получили все что там надо за разумный промежуок времени.


Можно использовать сигнальный байт как конец посылки. Если в посылке встречается байт такой же как и сигнальный, записываем за ним сигнальный байт.
Концом посылки будет нечётный подряд идущий сигнальный байт(точнее то что перед ним)Естественно данные придётся чистить от лишних сигнальных байт.
Указывать длину посылки проще.
Программа — мысли спрессованные в код.
Re: Как организовать корректный прием блочных данных по соке
От: Mr.Delphist  
Дата: 02.09.10 08:33
Оценка:
Здравствуйте, V-ctor, Вы писали:

VC>Вроде задача типовая и решения очевидно , но хотелось бы узнать как тут принято делать


Принято сначала втыкать заголовок фиксированной длины, где задаётся версия заголовка, размер последующего блока и т.п. Кроме непосредственной пользы при приёме, это даёт скрытый плюс — такие блоки данных можно оборачивать во внешний протокол, поодиночке или пачками (прецеденты встречались). Т.е. а-ля XML, только вместо обрамляющих тегов, в которые завернут inner xml, используется заголовок + длина.
Re: Как организовать корректный прием блочных данных по соке
От: V-ctor  
Дата: 02.09.10 08:57
Оценка:
Спасибо всем откликнувшимся. Да пожалуй передача заголовка с указанеим длинны наиболее приемлемый для меня вариант. Вообще оказывается все это хорошо освещено в книге "Эффективное программирование TCP/IP" совет 6, с примерами записи и чтения блочных данных из сокета. Может кому пригодицо. Жаль сразу не наткнулся на нее )))
Re: Как организовать корректный прием блочных данных по соке
От: legogogo  
Дата: 02.09.10 09:42
Оценка:
Здравствуйте, V-ctor, Вы писали:

VC>Надо скажем по сети передать кусок данных заведомо больший чем один tcp пакет


TCP это потоковый протокол.

VC>как на стороне приема правильно принять в том плане что у меня там идет прием пакаетов и мне надо как-то знать после приема первого надо ждат второй или это все данные.


Читаешь сокет, когда прочитаешь ноль байт это и есть конец, если дующее чтение вернёт ошибку.

VC>Входить в цикл и выгребать пока выгребается тоже как-то не очень ибо когда ничего нет , то непонятно, то ли по таймауту завершаем цикл приема ибо это все данные, то ли просто кто-то где-то споткнулся о кабель/образовался шторм в сети/еще какая неразбериха (а у нас в конторе к сожалению такое бывает из-за вечных экспериментов) и мы прсото не получили все что там надо за разумный промежуок времени.


Если данные можно доставить TCP доставит, проблемы сети это не проблемы протокола. В цикле использовать select/pselect/poll/ppoll/epoll, man recvmsg — > MSG_WAITALL
Компьютер — это конечный автомат. Потоковое программирование нужно тем, кто не умеет программировать конечные автоматы (c) Алан Кокс
Re[2]: Как организовать корректный прием блочных данных по с
От: legogogo  
Дата: 02.09.10 09:44
Оценка:
Здравствуйте, legogogo, Вы писали:

L>Читаешь сокет, когда прочитаешь ноль байт это и есть конец, следующее чтение вернёт ошибку.
Компьютер — это конечный автомат. Потоковое программирование нужно тем, кто не умеет программировать конечные автоматы (c) Алан Кокс
Re[2]: Как организовать корректный прием блочных данных по с
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 02.09.10 10:37
Оценка:
Здравствуйте, 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]: Как организовать корректный прием блочных данных по с
От: Vamp Россия  
Дата: 02.09.10 12:58
Оценка:
N>Правильно будет не так, а завести 3 других байта (отличающихся от сигнального): начало передачи, конец передачи и литеральная передача сигнала. Например, соответственно 1, x и 0. Тогда посылка AXB будет передана: X1AXxBX0. Этот метод используется (с вариациями на тему начальных посылок) в модемных протоколах (семейство Zmodem, Hydra, V.42, LAPM...)
Не понял, а зачем нужен отдельный маркер окончания посылки? Чем не устраивает общий маркер — начало/конец? Коррекция ошибок?
Да здравствует мыло душистое и веревка пушистая.
Re[4]: Как организовать корректный прием блочных данных по с
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 15.09.10 06:19
Оценка:
Здравствуйте, Vamp, Вы писали:

N>>Правильно будет не так, а завести 3 других байта (отличающихся от сигнального): начало передачи, конец передачи и литеральная передача сигнала. Например, соответственно 1, x и 0. Тогда посылка AXB будет передана: X1AXxBX0. Этот метод используется (с вариациями на тему начальных посылок) в модемных протоколах (семейство Zmodem, Hydra, V.42, LAPM...)

V>Не понял, а зачем нужен отдельный маркер окончания посылки? Чем не устраивает общий маркер — начало/конец? Коррекция ошибок?

Угу. С общим маркером у тебя получается, что всё, что между маркерами, должно рассматриваться как пакет и проверяться на корректность. Это, возможно, приемлемо в контексте данного треда (в случае TCP наливается столько данных, сколько хочешь), но для каналов связи неудобно. Для них, в случае короткого пропуска передачи, гонят крайние маркеры, а длинного — специальный код "покой линии". Мне тут привычнее говорить в контексте каналов связи, да и понимается с двумя раздельными маркерами обычно проще, чем с одним на начало и конец.
The God is real, unless declared integer.
Re[2]: Как организовать корректный прием блочных данных по с
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 16.09.10 06:04
Оценка:
Здравствуйте, AlexCrush, Вы писали:

AC>Вообще то вариантов два — или предварительная передача длины, или маркер конца (как в HTTP — два конца строки)

В HTTP используется и то, и другое
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.