|
Вопрос # 2 907/ вопрос открыт / |
|
Здравствуйте!
Помогите разработать прикладной протокол. База - компоненты TIdTCPClient и TIDTCPServer из Indy 10.
 |
Вопрос задал: Roman Novikov (статус: Посетитель)
Вопрос отправлен: 13 июня 2009, 21:30
Состояние вопроса: открыт, ответов: 1.
|
Ответ #1. Отвечает эксперт: Вадим К
Здравствуйте, Roman Novikov!
Разрабатывать абстрактный протокол - это весело. Но попробуем. Во первых, если одна сторона пишет данные в сокет в определённом порядке, то на принимающей стороне они придут именно в том порядке, в каком были отправлены и байты не будут "случайно пропущены". Это справедливо для протокола TCP. (для UDP свои правила).
Поэтому в наиболее простом случае можно делать по разному. Я расскажу как сделано в случае всем известной ICQ (в упрощенном варианте). Каждый пакет начинается с одного и того же байта. Это сделано для самоконтроля. дальше идет два байта счетчика текущего пакета (реально - не нужно, аська перестраховывается, так как в древние времена пакеты всё таки могли теряться...). и ещё два байта - тип пакета. А дальше собственно данные пакета. У них там хитро, а я рекомендую делать первые 4 байта длинной пакета с данными. в таком случае можно будет вычитать и обработать.
А теперь к реальному протоколу, который я например использовал.
вначале заголовок - 12 байт. первый байт один и тот же, $AA, потом 4 байта - тип пакета, 4 байта длина пакета с данными и следующие 3 байт нули, под будущее. А дальше были собственно данные.
А читать было просто - прочитал 12 байт, проанализировал, выделил буфер (вот тут надо быть аккуратным, а то кто то может пакет подменить, и размер сделать в 4 гига...., хотя бы банальную проверку, что пакет не может быть больше мегабайта или сколько там...). и следующим запросом ReadBuffer вычитываем данные.
Запись аналогично. подготовили буфер, заголовок, записали с помощью WriteBuffer.
Не надо бояться, что данные "перемешаются, будут недочитаны" и так дальше. Это уже сам протокол TCP обслуживает. Единственное, чего надо бояться - это дисконнекта. Но в этом случае данные просто будут недочитаны. Но не более...
Еще один протокол, который я делал, обменивался xml подобными строками. Правда у меня был класс, который умел сохранять мои классы (почти произвольные) в xml, а на другой стороне "восстанавливать". И использовал я более высокоуровневую методику - http.
Это всё вкратце. Пишите, что не понимаете и что хотите, напишем идеи.
 |
Ответ отправил: Вадим К (статус: Академик)
Время отправки: 14 июня 2009, 02:08
Оценка за ответ: 5
Комментарий к оценке: Вадим, хочется подробно пообщаться с вами... в аське не достучался.
Не совсем понял про первый байт - $AA, то есть это символ какой-то?
Тип пакета - это конкретно код функции? Длина пакета - вещественным числом?
Сейчас я использую функции Readln и Writeln... можно их или лучше стоит работать через буфер?
Я раньше участвовал в проекте и частично видел идею... там первым параметром в строке (строку формировали из служебных данных и самих данных) было что-то вроде $QQQQ, затем border - как разделяются данные, затем код приложения, код функции на клиенте, md5 и количество параметров. То есть было вроде такого:
"$QQQQ
border=;#13#10#
13#10
appl_id=1.1;#13#10
func_id=1;#13#10
length=15;#13#10
param1=value1;#13#10
param2=value3;#13#10
... ... ... ... ...
param15=value15;#13#10"
Это все доолжно быть в 1 строке, я для наглядности разбил по строкам и еже сами наименования параметров не обязательны.
Но в этой записи не ясно как сделать короткий border и чтобы он случайно не совпал с тем что может быть отправлено в данных от клиента.
|
Мини-форум вопроса
Всего сообщений: 15; последнее сообщение — 12 июля 2009, 15:28; участников в обсуждении: 3.
|
min@y™ (статус: Доктор наук), 14 июня 2009, 10:00 [#1]:
Дадада, мы с дружбаном писали когда-то чат. Для передачи сообщений и параметров текста использовали XML. Очень удобно, хотя и существует информационная избыточность, зато никаких проблем с добавлением новых параметров. Рекомендую.
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
|
|
Roman Novikov (статус: Посетитель), 15 июня 2009, 01:15 [#2]:
min@y™, а могли бы вы привести пример?
|
|
min@y™ (статус: Доктор наук), 15 июня 2009, 08:18 [#3]:
Цитата:
min@y™, а могли бы вы привести пример?
Пример чего?
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
|
|
Roman Novikov (статус: Посетитель), 15 июня 2009, 19:10 [#4]:
Пример протокола, основные важные моменты и рекомендации.
|
|
Вадим К (статус: Академик), 15 июня 2009, 19:26 [#5]:
"Не совсем понял про первый байт - $AA, то есть это символ какой-то?"
это просто шестнадцатеричная форма записи целого числа 170. Не более. Делфи так понимает.
"Тип пакета - это конкретно код функции?"
Тип пакета - это как бы что там будет, что бы код знал, как интерепретировать, что ему прислали. В грубом приближении можно считать, что это код команды.
"Длина пакета - вещественным числом?"
Упс, с каких пор???? два с половиной байта.... да.... круто не знал, что так можно.
"Сейчас я использую функции Readln и Writeln... можно их или лучше стоит работать через буфер?"
Можно по разному.
"Аська"... я в ней никого не авторизирую, даже наоборот. Может быть просто спамфильтр пройти не можете? это да, это может быть.
Галочка "подтверждения прочтения" - вселенское зло.
|
|
Вадим К (статус: Академик), 15 июня 2009, 19:28 [#6]:
"Но в этой записи не ясно как сделать короткий border и чтобы он случайно не совпал с тем что может быть отправлено в данных от клиента."
А вот это не понятно. Боимся, что данные, которые клиент отправляет серверу и сервер отправляет клиенту смогут смешаться до кучи?
Галочка "подтверждения прочтения" - вселенское зло.
|
|
min@y™ (статус: Доктор наук), 15 июня 2009, 19:30 [#7]:
Протоколы у всех одни и те же - UDP/TCP. А вот XML - это для того, чтобы постоянно не переделывать правила формирования сообщений. Параметры сообщения, такие как, например, IP-адрес отправителя, ник, время, дата, сам текст сообщения, смайлы, ссылки на внешние файлы/картинки/звуки и тд и тп - всё находится в одном XML-тексте, имена тегов и параметров этих тегов которого заранее известны. Этот XML-документ и передаётся по сети в качестве сообщения, т.е. формируется на отсылающей стороне и расшифровывается на принимающей. Если в процессе разработки/доработки программы туда что-то добавляется, то это добавление никак не сказывается на старых версиях программы. К тому же использование XML очень сильно облегчает отладку, т.к. вся передающаяся информация в исходном виде удобочитаема невооружённым глазом, кроме, конечно, бинарных файлов. Для передачи мы их кодировали в base64 и пихали в тот же XML.
Рекомендация: Имхо, лучший класс для работы с XML - это не TXMLDocument; мне нравится TECXMLParser.
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
|
|
Roman Novikov (статус: Посетитель), 16 июня 2009, 00:59 [#8]:
>Боимся, что данные, которые клиент отправляет серверу и сервер отправляет клиенту смогут смешаться до кучи?
Но ведь может же клиент отправить случайно набор символов которые совпадут с бордером.
|
|
Roman Novikov (статус: Посетитель), 16 июня 2009, 01:02 [#9]:
"Аська"... да, вроде на спам-фильтр правильно ответил, а не пущает)
|
|
Roman Novikov (статус: Посетитель), 16 июня 2009, 01:02 [#10]:
с длиной погорячился
|
|
Вадим К (статус: Академик), 16 июня 2009, 01:30 [#11]:
Теперь понял, что за "случайно совпадут". На самом деле - нет. А если совпадут - то это программист виноват. Пусть строка будет вида
border=border;#13#10#
13#10
appl_id=border;#13#10
Вот такую строку не разберете?
Галочка "подтверждения прочтения" - вселенское зло.
|
|
Roman Novikov (статус: Посетитель), 16 июня 2009, 17:28 [#12]:
Вопрос в том, как избежать "совпадения".
Разобрать строку могу. Но если взять border который я указал в примере, а пользователь в сообщении тоже вставит ";#13#10", то произойдет ошибка разбора строки. Как правильно поступить?
|
|
Вадим К (статус: Академик), 16 июня 2009, 17:40 [#13]:
вариант а - не дать пользователю так делать и проверять строки перед формированием пакета.
вариант б - сделать как в html - там есть спецсимволы. Если их надо вставить "как есть", то они заменяются на специальные конструкции.
Вариант, что злоумышленник специально подделает данные надо рассматривать отдельно.
Галочка "подтверждения прочтения" - вселенское зло.
|
|
Roman Novikov (статус: Посетитель), 12 июля 2009, 15:23 [#14]:
Как правильно записать добавление к строке идентификатор приложения? У меня Delphi2009. То есть все строки уже должны быть в юникоде. Как в начало пакета добавить набор символов юникода, обозначающих приложение(те же два байта $AA)?
|
|
Roman Novikov (статус: Посетитель), 12 июля 2009, 15:28 [#15]:
>>вариант а - не дать пользователю так делать и проверять строки перед формированием пакета.
Думается сделать стандартный бордер типа ";#13#10" и проверять его вхождение в данные. В случае вхождения добавлять к бордеру дополнительные символы и снова проверять до повяления уникальности.
|
Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.
|