Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Основы разработки программного обеспечения на примере языка С. Учебное пособие для СПО

.pdf
Скачиваний:
0
Добавлен:
07.09.2026
Размер:
2 Мб
Скачать
☆
При одиночной ошибке (табл. 9.1(б)) четвертого бита в первом байте мы легко установим, что байт был принят неверно. Количество единичных разрядов в нем оказалось при приеме нечетным (семь). Но мы не знаем, какой разряд был искажен.
Таблица 9.1(б). Пример
сообщения с ошибкой
Разряды: 0 1 2 3 4 5 6 7 к.р.
0 байт 1 0 1 1 0 1 0 1 1
1 байт 1 1 1 0 0 1 0 1 1
2 байт 0 0 1 0 0 0 1 0 0
3 байт 1 1 1 1 0 0 1 0 1
4 байт 0 0 0 1 1 0 1 1 0
Контр.байт 1 0 0 1 1 0 1 1 1
Это может быть любой из информационных разрядов. А может, мы неверно приняли контрольный разряд байта? Выяснить это удастся только после приема контрольной суммы всего сообщения. Сам байт контрольной суммы дополнен контрольным разрядом и принят правильно (содержит шесть единиц). А при расчете контрольной суммы по колонкам (разрядам) сообщения мы поймем, что в четвертом разряде в контрольной сумме допущена ошибка.
Это позволяет установить, что при приеме первого байта сообщения четвертый разряд был искажен. Мы получили 1, а должны были получить 0.
Конечно, таким образом могут быть обнаружены и исправлены только единичные ошибки в сообщениях. Для более ненадежных линий связи приходится применять избыточные коды с более сложными алгоритмами обнаружения и устранения ошибок. Кроме того, надо помнить и соблюдать правила взаимодействия с партнерами, т.е. строго выполнять те соглашения о связи, которые оформляются в протоколах обмена.
9.3. Протоколы обмена
Основы разработки программного обеспечения на примере языка СС.В. Синицын, О.И. Хлытчиев
191
Ранее уже говорилось, что при взаимодействии с формальными механизмами обе стороны общения обязаны соблюдать некоторый протокол (договоренность) обмена данными. Так, для случая, когда имеются один источник данных (передатчик) и несколько приемников, часто используется протокол ARINC 429 (ГОСТ 18977-79). Он использует в качестве единицы передачи слово, содержащее 32 разряда.
Таблица 9.2. Формат слов ГОСТ 18977-79
32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12
к/ р
Сп.Код Поле данных
к/ р
Количество слов сообщения
к/ р
Символ 3 Символ 2 Символ 1
к/ р
Обычно контрольный разряд (к/р) ARINC-слова выбирается так, чтобы сумма единиц в слове была нечетной. При этом, как и в большинстве систем передачи данных, контроль целостности принятого слова выполняется на аппаратном уровне. За программой остается только проверка контрольной суммы и интерпретация принятого сообщения.
Младшие разряды слова отводятся под двоично-восьмеричный код метки слова. Слова с различными метками имеют различную интерпретацию в протоколе и различный формат. Сама метка записывается по традиции справа налево. Так, код метки с восьмеричным номером 012 (прямое представление 0 001 010) будет в разрядах 1-8 выглядеть так: 0101000.
Такое представление сохранилось с тех пор, когда слово передавалось по последовательному каналу, принималось и обрабатывалось в сдвиговом регистре. При этом метка поступала на обработку первой. А по завершении приема слова можно было сформировать и проверить контрольный разряд. В настоящее время чаще слово передается побайтово, но традиции кодирования справа налево сохранились.
Основы разработки программного обеспечения на примере языка СС.В. Синицын, О.И. Хлытчиев
192
Поле "Ид.Ист." позволяет закодировать источник данных (сообщения). Понятно, что их не может быть более четырех. В ряде случаев это поле служит для указания адресата - приемника данных.
Поле "Сп.Код" применяется для кодирования специальной информации
- расширения поля данных. Например, в нем может указываться знак числа, направление ветра (юг, восток, север, запад) и т.п.
В тех случаях, когда передается пакет текстовых данных, в теле сообщения используются слова с TXT-метками, содержательная часть которых включает три символа (7-разрядных). В поле "Сп.Код" указываются признаки "первый/последний". В тех случаях, когда длина сообщения не кратна трем, по соглашению полагается заполнять поля неиспользуемых символов нулями.
Кроме упомянутых в разделе 9.1 меток STX, ETX, RTS, ACK, NAK, ориентированных на передачу пакетов данных, протокол ГОСТ 18977­79 предусматривает и такие слова, которые полностью самодостаточны. Их поля данных могут интерпретироваться как текущая высота, скорость, сила ветра, состояние устройства (биты признаков) и т.п.
Как правило, протокол подобного обмена включает периодическую посылку "пустого" слова (Zero Label). Его появление на шине обмена говорит о том, что источник данных "жив" и нормально функционирует. Отсутствие подобного слова в течение двойного периода посылки означает для приемника либо обрыв линии передачи, либо отказ источника данных.
Другой протокол (ГОСТ 27765.52-87) предназначен для организации связи нескольких устройств по магистральной (обычно последовательной) шине данных. При этом используются 20-битовые слова, содержащие в начале 3 специальных синхронизирующих бита (sss). По ним аппаратура связи может настроиться на прием слова.
Таблица 9.3. Формат слов ГОСТ 27765.52-87
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
s s s Адрес ОУ Длина сообщения
s s s Данные
s s s Адрес ОУ Ош Ос Зн н/и к/р
Основы разработки программного обеспечения на примере языка СС.В. Синицын, О.И. Хлытчиев
193
При приеме слова аппаратура обслуживания линии связи использует первые три разряда для настройки на прием передаваемых данных. Последним принимается контрольный разряд, который, как правило, проверяется на аппаратном уровне. Бит четности (к/р) формируется так, чтобы количество единиц у 17-и информационных разрядов было нечетно.
В содержательной части (оставшиеся 16 бит) содержится код (адрес оконечного устройства) приемника (адресата), длина сообщения и различная управляющая информация. В ее состав, так же как и в ARINC-протоколе, может включаться дополнительно код источника данных. В ответном слове (10-й разряд Ос = 1) принимающая сторона может установить код ошибки (9-й разряд), признак "Абонент занят" (16­й разряд), "Абонент неисправен" (17-й разряд) и т.п. Традиционно посылка пакета начинается по инициативе передатчика (источника) данных и заканчивается ответным словом приемника.
Как правило, код оконечного устройства 11111 предназначен для одновременной передачи команды нескольким приемникам сразу. При этом не предусматривается прием ответного слова. Их может быть больше одного и разных по содержанию (кто-то принял, а кто-то не принял). Такие "широковещательные" команды могут обеспечить повышение скорости передачи данных, но, безусловно, снижают надежность доставки.
Поскольку вероятность появления отказа в линии связи тем больше, чем длиннее передаваемое сообщение, косвенным способом повышения надежности передачи может служить сжатие данных перед отправкой. Конечно, при этом увеличиваются временные затраты на подготовку (сжатие, кодирование) пакета перед отправкой и его восстановление (декодирование) в пункте приема. Однако в ряде случаев это с лихвой окупается за счет увеличения надежности и уменьшения времени передачи.
9.4. Кодирование для сжатия информации
Алгоритмы кодирования нередко используются для сжатия не только при передаче, но и при архивации данных. Одним из таких примеров
Основы разработки программного обеспечения на примере языка СС.В. Синицын, О.И. Хлытчиев
194
является кодирование текстовой информации в сервисе коротких сообщений в мобильной связи (SMS-сервис). Текст в сообщении передается в сжатом виде.
В большинстве случаев для каждого символа текста отводится один байт, что верно и для представления текстовой (строковой) информации в языке Си. Однако из ASCII-таблицы чаще всего используются лишь первые 127 символов, включающие в себя английский алфавит, цифры, основные знаки препинания и служебные дополнительные символы (например, * или \ ). Очевидно, что для хранения этих символов достаточно лишь 7 бит (127 значений для кода символа), т.е. несколько меньше байта. Такой подход как раз и используется при кодировании SMS-сообщений, что позволяет передать больше символов в одном сообщении.
Первые поколения GSM-сетей не позволяли передавать данные на большой скорости и не позволяли совмещать передачу данных и голосовой звонок. Поэтому чем короче сообщение, тем меньше занимает эфирного времени его передача и тем меньше времени абонент занят для голосового звонка. Стандарт GSM выделяет максимум 160 байт для одного текстового сообщения, 20 из которых - служебная информация. На сам текст остается 140 байт, в которых при 7-битовом кодировании можно разметить 160 текстовых символов.
Рассмотрим алгоритм реализации такого кодирования. Однако прежде чем перейти к коду алгоритма, следует учесть еще один факт. Большинство устройств, отвечающих за передачу данных в GSM-сетях, являются модемами, которые взаимодействуют с другими устройствами посредством стандартного протокола, т.е. при помощи так называемых AT-команд. Эти команды можно посылать модему через терминал (последовательный поток ввода и поток вывода). При этом передаваемая бинарная информация представляется побайтово в шестнадцатеричном виде, чтобы не возникало конфликтов с управляющими AT-командами. Например, если в тексте сообщения содержится символ "1" (имеющий ASCII-код 49), то для 1-байтового кодирования он имел бы двоичное представление: 00110001. Для 7битного кодирования он имеет вид: 0110001.
А при передаче его через терминал он будет представлен двумя
Основы разработки программного обеспечения на примере языка СС.В. Синицын, О.И. Хлытчиев
195
символами как "31", т.е. в виде шестнадцатеричного числа 31, представленного как текст (именно двумя символами, а не одним символом с кодом 31). Поэтому при кодировании текста для передачи SMS необходимо его не просто закодировать в 7-битный код, но затем еще и представить его в виде шестнадцатеричного текстового кода, "понятного" GSM-модему.
Из 1-байтового представления текста 7-битный код получается следующим образом. Для первого символа берутся семь младших бит и записываются в семь младших бит первого байта результата. Далее от второго символа исходного текста берутся шесть младших бит и записываются в шесть младших бит второго байта результата. От второго символа остается один (7-й) значащий бит, который записывается в старший 8-й бит первого байта результата (который как раз не использован для хранения первого символа). Для третьего входного символа в третий байт результата записывается только пять младших бит. А два остающихся значащих бита (7-й и 6-й) сохраняются соответственно в 8-м и 7-м битах второго байта результата (они как раз не использованы для хранения второго символа). При обработке восьмого символа оказывается, что его нулевой бит надо записать в восьмой байт результата, а все его значащие биты поместятся в старшие семь разрядов 7-го байта результата. Таким образом, для восьми символов потребуется всего семь байт. Далее процесс повторяется. Описанная схема представлена на рис. 9.1
.
Рис. 9.1. Семибитное кодирование строки "Hello C!" в SMS
Основы разработки программного обеспечения на примере языка СС.В. Синицын, О.И. Хлытчиев
196
Рис. 9.2. Работа функции encodeToPDU для строки "Hello C!"
Реализация метода кодирования на языке Си может иметь следующий вид:
void encodeToPDU(char *text, char *res) { int len; int i, j; int shift; unsigned char prevNum, curNum, tmpVal1, tmpVal2, curValue; j = 0; i = 0; prevNum = 0; len = length(text); tmpVal1 = 0; tmpVal2 = 0; while(i < len) { curNum = (unsigned char)text[i]; /* special code for symbol @ */ if (text[i] == '@') {curNum = 0;} shift = (i %8); curValue = curNum & 127; curValue = (curValue >> shift); tmpVal2 = curValue; if (i > 0)
Основы разработки программного обеспечения на примере языка СС.В. Синицын, О.И. Хлытчиев
197
{ prevNum = (curNum << (8 - shift)); tmpVal1 = tmpVal1 | prevNum; } if (shift != 7) { if (i > 0) { res[j] = decToHex(tmpVal1 / 16); res[j + 1] = decToHex(tmpVal1 % 16); j+=2; } tmpVal1 = tmpVal2; } i++; } res[j] = decToHex(tmpVal1 / 16);; res[j + 1] = decToHex(tmpVal1 % 16); res[j + 2] = '\0'; }
Здесь используется функция нахождения длины строки length:
int length(char *str) { int i; i = 0; while(*str++) { i++; } return i; }
Выделение нужного количества бит в байте реализуется в языке Си посредством сдвига. При помощи этой же операции можно выставить значащие биты на нужные позиции. Для "удаления" незначащих бит
Основы разработки программного обеспечения на примере языка СС.В. Синицын, О.И. Хлытчиев
198
можно использовать логическую операцию И с числом-маской, в котором на позиции незначащих бит выставляются нули, а на позиции значащих - единицы. После операции И с таким числом-маской все незначащие биты становятся равными нулю.
Приведенная функция encodeToPDU принимает на вход текст из параметра text и двигается по нему посимвольно, для задания текущей позиции используется переменная i. Выходная строка res также формируется последовательно в один проход (рис. 9.2
).
Для всех входных символов перед их обработкой выполняется операция И с маской 127 (01111111) для выставления в 0 незначащего старшего бита:
curNum = (unsigned char) text[i] ; curValue = curNum & 127;
После этого для каждого символа входной строки вычисляется сдвиг, на который необходимо сдвинуть значащие биты вправо, чтобы далее записать оставшееся количество значащих бит в текущий выходной байт. Текущий выходной байт сохраняется в переменную
tmpVal2: curValue = (curValue >> shift); tmpVal2 = curValue;
Количество бит, записываемых в текущий выходной байт, как раз равно сдвигу. Сдвиг считается как
shift = (i % 8);
Для первого символа он равен нулю, далее возрастает на каждом шаге на единицу. Для восьмого символа он оказывается равен семи, т.е. все значащие биты сдвигаются и ни один из них не записывается в текущий выходной байт (в 8-й выходной байт). Все сдвинутые биты записываются в предыдущий выходной байт, который сохраняется в переменной tmpVal1. Для этого текущий входной байт сдвигается на
Основы разработки программного обеспечения на примере языка СС.В. Синицын, О.И. Хлытчиев
199
величину (8 - shift) влево, т.е. нужное количество значащих бит оказывается в старших разрядах:
if (i > 0) { prevNum = (curNum << (8 - shift)); tmpVal1 = tmpVal1 | prevNum; }
И только для первого входного символа и соответствующего ему первого выходного байта не надо сохранять ничего в предыдущий выходной байт.
Для восьмого входного символа все семь значащих бит записываются в 7-й байт результата. После каждого перехода к следующему символу во входной строке необходимо сохранить текущий выходной байт в переменную tmpVall, чтобы "освободить" для следующего шага переменную tmpVal2:
if (shift != 7) { ... tmpVal1 = tmpVal2; }
Такое перемещение не надо выполнять только для каждого восьмого входного символа, когда все семь значащих бит сохраняются в предыдущий выходной байт, а текущий оказывается незаполненным (shift = 7).
Как уже было отмечено, кодирование происходит в один проход. В результате выполнения функции получается не бинарный код, реально отправляемый в SMS, а его шестнадцатеричное представление, которое можно передать GSM-модему посредством терминала. По-этому каждый выходной байт представляется в виде пары шестнадцатеричных цифр:
res[ j] = decToHex(tmpVal1 / 16); res[ j + 1] = decToHex(tmpVal1 % 16);
Основы разработки программного обеспечения на примере языка СС.В. Синицын, О.И. Хлытчиев
200
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]