| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Алгоритмы > составить алгоритм расчета контрольной суммы |
| Автор: Hypertonyc 8.3.2011, 11:24 | ||
| Здравствуйте. Имеются клиент и сервер которые обмениваются данными по сети. На каждый пакет клиента сервер отвечает пакетом данных по 9 байт. Первые два и последний во всех пакетах одинаковые. Предпоследний - это контрольная сумма вычисленная по 3ему,4,5,6, и 7му байтам. Собственно в этом и проблема, никак не пойму алгоритма расчета. Очень прошу гляньте свежим взглядом, боюсь ответ на поверхности просто у меня "инерция мышления" уже. Прилагаю исходник моей небольшой программки(C++) по расчету этой контр.суммы(думаю к ней комментариев не требуется) и список пакетов полученных с реального сервера этой системы. P.S. большинство сумм в пакетах реально рассчитываются корректно по моему алгоритму, но в списке встречаются пакеты где контр.сумма=0x00(например #23808), а в моём алгоритме 0 ну никак не получится какие бы цифры не подставь(поэтому алгоритм отстой :()
|
| Автор: Hypertonyc 8.3.2011, 22:21 |
| возможно не ясна причина моего внимания этому алгоритму. так вот дело в том что я пишу свой сервер, который должен работать в том числе и с клиентами из описанной в первом посте системы. схема работы системы: - клиент шлет пакет с данными (N байт); - сервер, приняв пакет, копирует заголовок принятого пакета (7 байт) рассчитывает по ним(7ми байтам) контрольную сумму(1 байт) и прикрепляет в конец пакета+конечный байт везде одинаковый(итого 9 байт); - клиент приняв 9ти байтовый ответ шлет на сервер следующий пакет с данными; так вот когда в мой сервер приходят данные он копирует шапку и по ней считает контр.сумму формирует 9байтовый ответ и шлет клиенту. Клиент не воспринимая ответ должным образом(т.к. ответ является некорректным(не совпадает тот самый предпоследний байт(контр.сумма)) ) вместо новых данных повторно посылает старые...и всё покругу пока не надоест надеюсь что-нибудь понятно. |
| Автор: Hypertonyc 13.3.2011, 09:53 |
| |
| Автор: Peter 13.3.2011, 09:59 | ||||
| Кажется понятно. Неверно вычисляется контрольная сумма. Так? Первое, что бросается в глаза при просмотре программы, это
tmp_crc имеет размер 2 байта, а bytes[i] - 1 байт. Если мы сдвигаем эту байтовую переменную влево (хоть вправо), всё равно получаем 1 байт. "Лишние" биты во второй байт не уползают, так как его нет. Если надо, чтобы они переползали во второй байт, надо однобайтную переменную сделать двухбайтной.
|
| Автор: Hypertonyc 13.3.2011, 10:02 | ||
ну вообще-то "уползают".(компилил в VC2008) Добавлено через 1 минуту и 39 секунд И вообще изначально мой алгоритм отстой из-за: 0xaf 0xff 0x09 0x80 0xd7 0x08 0x00 0x04 0xfa ((0x09*16 + 0x80*8 + 0xd7*4 + 0x08*2 + 0x00*1) -> 07fc > 0xFF -> 07+fc -> 0103 -> 0x04) 0xaf 0xff 0x09 0x84 0xd3 0x00 0x00 0x00 0xfa ((0x09*16 + 0x84*8 + 0xd3*4 + 0x00*2 + 0x00*1) -> 07fc > 0xFF -> 07+fc -> 0103 -> 0x00(!)) если все байты складывать, то получаются абсолютно одинаковые числа что говорит о том что числа должны не просто складываться, а при каких-то условиях, либо там не сложение а другая операция,либо потом накладывается маска. |
| Автор: Peter 13.3.2011, 10:15 |
| Именно, что не уползают. Считаем этот 23808-й пакет. 0x09 << 4 = 0x90 0x00 << 3 = 0x00 0x5c << 2 = 0x70 0xff << 1 = 0xfe 0x00 << 0 = 0x00 Складываем результаты (с учетом, что они присвоены двухбайтной переменной), получаем 0x01fe. Складываем первый и второй байты (0x01 и 0xfe) - получаем 0x0100. Преобразовываем его к одному байту (ведь только один байт контрольный) - получаем 0x00. Добавлено через 6 минут и 19 секунд Ошибся. Невнимательно посмотрел алгоритм. Там результат 0x0100 не к байту приводить надо, а опять на биты разбивать и складывать. И получится 0x0001. Значит, чтобы получить 0x00, надо тело последнего цикла выполнять только 1 раз (т.е. цикла не будет) и результат приводить к байту. |
| Автор: Hypertonyc 13.3.2011, 10:31 | ||
а как тогда здесь 0х04 вышло? 0xaf 0xff 0x09 0x80 0xd7 0x08 0x00 0x04 0xfa и еще интересно как это у Вас так : fe+01=100? |
| Автор: Peter 13.3.2011, 10:34 |
| Да, здесь 0х04 не получается... Значит, вопрос в том, чтобы подобрать алгоритм? |
| Автор: Hypertonyc 13.3.2011, 10:38 | ||
ИМЕННО!!! |
| Автор: Hypertonyc 14.3.2011, 16:27 |
| |
| Автор: Peter 14.3.2011, 17:26 |
| В приложенном файле только два байта - пятый и шестой - изменяются, а третий и четвертый - нет. Так что какую-то зависимость от двух переменных подобрать можно, а от всех четырех - недостаточно информации. |
| Автор: Hypertonyc 14.3.2011, 21:05 | ||
| увеличил количество пакетов и сделал автоматизированную проверку с выводом пакетов с неверной к.суммой в отдельный файл списки пакетов: http://rghost.ru/4766108 – все пакеты http://rghost.ru/4766189 – результат программы(пакеты где контр.сумма рассчитана с ошибкой)
p.s. результат программы 0.39% not good |
| Автор: Peter 15.3.2011, 10:43 |
| Цифра 0.39% похожа на 1/256. Я бы сравнил две соседние строчки, в первой из которых контрольный байт рассчитан правильно, а во второй - неправильно; и подумал бы, в чем может быть недостаток алгоритма. |
| Автор: volatile 16.3.2011, 13:06 | ||
| Интересная головоломка! Убил сегодня 2 часа разгадывая её. Получилась вот такая процедурка Не факт что на других данных будет все ок, но на тех данных что есть, всё гуд! Проходит большой файл 'list.txt' (13Мб) = без единой ошибки. Ловите
А задачка действительно очень интересная, даже поискал в нете, что-то подобное. Наткнулся только на ваши вопросы. Если честно, думаю что решение должно быть конечно проще, но пока вот так вот, да и данных недостаточно. Давно пытаетесь решить? |