Визуализация сообщений модема Sierra MC7710 для программы WireShark
Графический интерфейс программного продукта WireShark. Правила разработки программно подключаемых модулей WireShark. Программное обеспечение, реализующее визуализацию сообщений модема Sierra MC7710. Тестирование разработанной программы isfreader.
Рубрика | Программирование, компьютеры и кибернетика |
Вид | курсовая работа |
Язык | русский |
Дата добавления | 29.05.2013 |
Размер файла | 2,0 M |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
Размещено на http://www.allbest.ru/
КУРСОВАЯ РАБОТА
Визуализация сообщений модема Sierra MC7710 для программы WireShark
МОСКВА 2013
ОГЛАВЛЕНИЕ
- ВВЕДЕНИЕ
- ГЛАВА 1. Методы разработки и подключения программно подключаемых модулей сетевого анализатора wireshark
- 1.1 Графический интерфейс программного продукта WireShark
- 1.2 Правила разработки программно подключаемых модулей WireShark
- 1.3 Правила использования программно подключаемых модулей WireShark
- Выводы по главе 1
- ГЛАВА 2. Программное обеспечение визуализации сообщений модема sierra mc7710
- 2.1 Интерфейс программного модуля СПО QXDM Professional
- 2.2 Программное обеспечение, реализующее визуализацию сообщений модема Sierra MC7710
- 2.3 Программное обеспечение, реализующее визуализацию сообщений модема Sierra MC7710 для программы WireShark
- 2.4 Тестирование разработанной программы isfreader
- Выводы по главе 2
- Заключение
- ЛИТЕРАТУРА
- Приложение 1
ВВЕДЕНИЕ
Цель настоящей работы - исследование возможности создания программно подключаемого модуля для программы WireShark, реализующего визуализацию сообщений модема Sierra MC7710
Задачами данной курсовой работы являются:
- практическое освоение правил разработки и подключения программных модулей WireShark;
- изучение интерфейса программного модуля СПО QXDM Professional;
- разработка программы, реализующего визуализацию сообщений модема Sierra MC7710, включая отображение специальной информации, полученной после обработки сообщений программным модулем СПО QXDM Professional;
- исследование возможности интеграции разработанной программы в виде программного модуля WireShark.
Курсовая работа состоит из двух глав. В первой главе рассмотрены принципы разработки и использования программно подключаемых модулей WireShark на примере тестовой программы.
Во второй главе описана разработка программы с возможностью отображения сообщений модема Sierra MC7710 в шестнадцатеричном формате и специальной информации, полученной после обработки сообщений программным модулем СПО QXDM Professional. Так же описано исследование возможности интеграции разработанной программы в качестве программно подключаемого модуля WireShark.
ГЛАВА 1. Методы разработки и подключения программно подключаемых модулей сетевого анализатора wireshark
1.1 Графический интерфейс программного продукта WireShark
Программный продукт Wireshark представляет собой анализатор сетевых протоколов с графическим интерфейсом. Программа позволяет просматривать и анализировать пакеты, полученные из сетевого интерфейса или ранее собранного файла.
Для начала сборки перехваченных программой пакетов сообщений по сети, необходимо выбрать пункт главного меню Capture>Interfaces или кнопку на верхней панели инструментов List the available capture interfaces - после этого на экране появится следующее диалоговое окно:
Рис. 1.1. Окно выбора интерфейса
С помощью кнопки Options можно установить желаемые параметры работы программы. Для того чтобы начать работу, необходимо нажать кнопку Start.
Сетевой анализатор Wireshark включает в себя 3 области просмотра с различными уровнями детализации. Верхнее окно содержит список собранных пакетов с кратким описанием, в среднем окне изображено дерево протоколов, инкапсулированных в кадр. Ветви дерева могут быть раскрыты для повышения уровня детализации выбранного протокола. Последнее окно содержит дамп пакета в шестнадцатеричном или текстовом представлении. Программа обеспечивает возможность сбора всех пакетов заданного соединения TCP и представления данных в удобном для просмотра формате.
Рис. 1.2. Начало работы ПО WireShark
В верхней панели по умолчанию содержится 6 колонок - номера пакета в списке собранных, временная метка, адреса и номера портов отправителя и получателя, тип протокола и краткое описание пакета. Выбрав необходимый пакет из списка можно просмотреть содержимое средней панели. В ней представлено дерево протоколов для пакета. Дерево отображает каждое поле и его значение для заголовков всех протоколов стека.
Рис. 1.3. Дерево протоколов
Программа обладает большим набором вывода статистических данных о захваченных пакетах сообщений. Так, можно вывести общую таблицу иерархии протоколов при помощи пункта главного меню Statistics>Protocol Hierarchy.
Рис. 1.4. Таблица иерархии протоколов
Для наглядного представления результатов выполнения захвата пакетов и сборки кадров в программе имеется возможность отображения данной информации в виде графика числа пакетов в единицу времени. Для отображения данного графика необходимо воспользоваться пунктом главного меню Statistics>IO Graphs.
Рис. 1.5. График сбора пакетов
1.2 Правила разработки программно подключаемых модулей WireShark
В качестве примера программно подключаемого модуля для программного продукта WireShark приведен пример диссектора для протокола foo.
Структура пакета протокола foo:
- 1 байт - версия протокола;
- 1 байт - тип пакета;
- 1 байт - всевозможные флаги;
- 1 байт - булева переменная;
- 4 байт - длина полезной нагрузки;
- От 0 до 200 байт - полезная нагрузка.
Рассмотрим реализацию диссектора на языке C++. Все диссекторы сетевого анализатора WireShark используют стандартные заголовочные файлы, такие как config.h, glib.h, и packet.h.
Листинг 1.1
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <epan/packet.h>
#define FOO_PORT 35000
//Номер UDP порта, на котором предполагаем будет находится FOO траффик.
static int proto_foo = -1;
/* При регистрации протокола переменная затрется идентификатором протокола. */
void proto_register_foo(void)
{
proto_foo = proto_register_protocol (
"FOO Protocol", /* полное имя */
"FOO", /* короткое имя */
"foo" /* аббревиатура */
);
}
Функция proto_register_protocol() регистрирует протокол и выдает его уникальный идентификатор. Функции передается три разных имени протокола, которые будут отображены в различных частях программы. (К примеру, имена «FOO Protocol» и «FOO» используются в настройках программного продукта Wireshark, а аббревиатура «foo» используется в поле фильтра.)
Функция create_dissector_handle() будет вызываться в случае необходимости расшифровать пойманный foo-пакет.
Листинг 1.2
void proto_reg_handoff_foo(void)
{
static dissector_handle_t foo_handle;
foo_handle = create_dissector_handle(dissect_foo, proto_foo);
dissector_add_uint("udp.port", FOO_PORT, foo_handle);
}
В данной части кода регистрируется обработчик-диссектор, который выполняет работу по разложению протокола по составу и привязываем его к протоколу proto_foo. Затем нужно связать обработчик с UDP портом, на котором будет ходить трафик. Таким образом, сетевой анализатор Wireshark вызовет соответствующую функцию, когда на заданном порту (35000) появится какая-либо активность. Есть соглашение, согласно которому фукнции proto_register_foo() и proto_reg_handoff_foo() необходио написать в конце нашего исходного файла.
Листинг 1.3
static void dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
col_set_str(pinfo->cinfo, COL_PROTOCOL, "FOO");
col_clear(pinfo->cinfo, COL_INFO);
}
Функция dissect_foo() будет вызываться для детальной работы над пакетом, который ей передан. Данные пакета хранятся в специальном буфере - tvb. В pinfo находится общая информация о протоколе. А в переменной tree происходят основные изменения, когда определяется конечный вид протокола на выходе. Данного кода достаточно, чтобы программный продукт WireShark подхватил программно подключаемый модуль.
Программно подключаемый модуль пока что не несет функциональной нагрузки, поэтому его необходимо дополнить. Для начала нужно создать ветку на дереве (tree), в которую будут помещены результаты декодирования. Диссектор вызывается в двух различных случаях: в одном случае, когда необходимо получить сводную информацию о пакете, и в другом случае, когда нужно вывести детальную информацию о том же пакете. Если указатель на tree равен NULL, значит нужна только сводная информация. Иначе - нужно заполнить tree детальной информацией, которая будет выведена пользователю. С учетом этого диссектор приобретает вид:
Листинг 1.4
static void dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
col_set_str(pinfo->cinfo, COL_PROTOCOL, "FOO");
col_clear(pinfo->cinfo, COL_INFO);
if (tree)
{
proto_item *ti = NULL;
ti = proto_tree_add_item(tree, proto_foo, tvb, 0, -1, FALSE);
}
}
В данном случае добавлена ветка в дерево (tree) вызовом proto_tree_add_item(). Эта ветка будет содержать все детали о foo протоколе. Так же необходимо пометить область данных в пакете, которую использует протокол. В данном случае - это вся область за границей данных UDP пакета.
Параметры функции proto_tree_add_item():
- tree - все дерево информации о пакете;
- proto_foo - идентификатор протокола;
- tvb - блок данных (данные, переданные протоколом);
- 0 - начиная с какой позиции данные в блоке tvb являются данными foo протокола;
- -1 - количество байт, занимаемое протоколом («-1» означает «до конца блока данных»);
- FALSE - указывается порядок байт (TRUE - если байты расположены в сетевом порядке).
После этих изменений программный продукт Wireshark начнет определять, где начинается и кончается область протокола и помечает ее как «FOO Protocol».
Следующим шагом будет добавление деталей. Для этого шага потребуется создание нескольких массивов и дополнительных вызовов функций, которые помогут при расшифровке. Изменения коснутся тела функции proto_register_foo(), показанной ранее. Нужно добавить два статических массива в начало proto_register_foo(). Затем необходимо зарегистрировать массивы после вызова функции proto_register_protocol().
Листинг 1.5
void proto_register_foo(void)
{
static hf_register_info hf[] = {
{ &hf_foo_hdr_version,
{ "FOO Header Version", "foo.hdr.version",
FT_UINT8, BASE_DEC,
NULL, 0x0,
NULL, HFILL }
},
{ &hf_foo_hdr_type,
{ "FOO Header Type", "foo.hdr.type",
FT_UINT8, BASE_DEC,
NULL, 0x0,
NULL, HFILL }
}
};
static gint *ett[] = { &ett_foo };
proto_foo = proto_register_protocol (
"FOO Protocol",
"FOO",
"foo" );
proto_register_field_array(proto_foo, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
}
Для детализации отображения протокола потребуется:
Листинг 1.6
if (tree)
{
proto_item *ti = NULL;
proto_tree *foo_tree = NULL;
ti = proto_tree_add_item(tree, proto_foo, tvb, 0, -1, FALSE);
foo_tree = proto_item_add_subtree(ti, ett_foo);
proto_tree_add_item(foo_tree, hf_foo_hdr_version, tvb, 0, 1, FALSE);
proto_tree_add_item(foo_tree, hf_foo_hdr_type, tvb, 1, 1, FALSE);
}
На данный момент будут распознаны лишь первые 2 байта foo протокола, которые отвечают за версию протокола и тип пакета. Вызов функции proto_item_add_subtree() добавит ветвь (foo_tree) с деталями о foo протоколе в дерево (tree) информации обо всем пришедшем пакете. В foo_tree будет детально описан наш протокол.
Переменной ett_foo контролируется «развертка» дерева информации о протоколе в выводе программы Wireshark.
Функция proto_tree_add_item() на этот раз использует переменную hf_foo_hdr_version для вывода значения в нужном формате. hdr_version - 1 байт из tvb, начиная с позиции 0. hdr_type - 1 байт из tvb, начиная с позиции 1.
Рассмотрим объявление hf_foo_hdr_version в статическом массиве, здесь находится детально описанное поле:
- hf_foo_hdr_version - индекс ветки;
- FOO Header Version - именование поля;
- foo.hdr.version - это строчка, используемая для фильтрации пакетов (такой вид строчки будет в поле фильтра);
- FT_UNIT8 - указывает на тип и размер элемента, который считывается из блока данных tvb. В данном случае указывает, что поле «версия протокола» занимает 1 байт типа unsigned integer. (Другие возможные типы можно найти в файле wireshark/epan/ftypes/ftypes.h);
- BASE_DEC - для числовых типов указывает, в какой системе выводить числа. (Также может быть BASE_HEX или BASE_OCT. Для нечисловых типов используем BASE_NONE).
Необходимо объявить еще несколько переменных и детализировать вывод.
Листинг 1.7
...
static int hf_foo_hdr_flags = -1;
static int hf_foo_hdr_bool = -1;
static int hf_foo_pl_len = -1;
static int hf_foo_payload = -1;
...
void proto_register_foo(void)
{
{ &hf_foo_hdr_flags,
{ "FOO Header Flags", "foo.hdr.flags",
FT_UINT8, BASE_HEX,
NULL, 0x0,
NULL, HFILL }
},
{ &hf_foo_hdr_bool,
{ "FOO Header Boolean", "foo.hdr.bool",
FT_BOOLEAN, BASE_NONE,
NULL, 0x0,
NULL, HFILL
}
},
{ &hf_foo_pl_len,
{ "FOO Payload Length", "foo.pl_len",
FT_UINT8, BASE_DEC,
NULL, 0x0,
NULL, HFILL
}
},
{ &hf_foo_payload,
{ "FOO Payload", "foo.payload",
FT_STRING, BASE_NONE,
NULL, 0x0,
NULL, HFILL
}
}
}
static void dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
...
if (tree)
{
gint offset = 0;
proto_item *ti = NULL;
proto_tree *foo_tree = NULL;
ti = proto_tree_add_item(tree, proto_foo, tvb, 0, -1, FALSE);
foo_tree = proto_item_add_subtree(ti, ett_foo);
proto_tree_add_item(foo_tree, hf_foo_hdr_version, tvb, offset, 1, FALSE); offset += 1;
proto_tree_add_item(foo_tree, hf_foo_hdr_type, tvb, offset, 1, FALSE); offset += 1;
proto_tree_add_item(foo_tree, hf_foo_hdr_flags, tvb, offset, 1, FALSE); offset += 1;
proto_tree_add_item(foo_tree, hf_foo_hdr_bool, tvb, offset, 1, FALSE); offset += 1;
proto_tree_add_item(foo_tree, hf_foo_pl_len, tvb, offset, 4, TRUE); offset += 4;
proto_tree_add_item(foo_tree, hf_foo_payload, tvb, offset, -1, FALSE);
}
}
Таким образом, расшифрованы все биты протокола. Теперь сетевой анализатор Wireshark имеет достаточно хорошее представление о протоколе. Но необходимо описать обработку поля flags, которое нужно раскладывать побитно вручную. А также, в случае, если версия протокола неизвестна, можно ли доверять выводу. Диссектор будет генерировать исключение, если пакет придет без поля payload и с нулевым значением pl_len.
Далее нужно определить обработку именования версии и типа пришедшего пакета, что позволит гораздо быстрее воспринимать информацию при просмотре пакета. Для этого нужны два массива.
Листинг 1.8
static const value_string packetversions[] = {
{ 1, "Version 1" },
{ 0, NULL }
};
static const value_string packettypes[] = {
{ 1, "Ping request" },
{ 2, "Ping acknowledgment" },
{ 3, "Print payload" },
{ 0, NULL }
};
Зависимость в массивах - «значение, имя значения». Таким образом, при просмотре пакета можно видеть не голый номер типа пакета, а сразу описание типа. Для доступа к этим массивам будут задействованы VALS-макросы, которые предоставляются самим программным продуктом Wireshark.
Листинг 1.9
{ &hf_foo_hdr_version,
{ "FOO Header Version", "foo.hdr.version",
FT_UINT8, BASE_DEC,
VALS(packetversions), 0x0,
NULL, HFILL }
},
{ &hf_foo_hdr_type,
{
"FOO Header Type", "foo.hdr.type",
FT_UINT8, BASE_DEC,
VALS(packettypes), 0x0,
NULL, HFILL
}
}
Теперь необходимо осуществить корректную обработку флагов поступившего пакета.
Листинг 1.10
#define FOO_FIRST_FLAG 0x01
#define FOO_SECOND_FLAG 0x02
#define FOO_ONEMORE_FLAG 0x04
static int hf_foo_flags_first = -1;
static int hf_foo_flags_second = -1;
static int hf_foo_flags_onemore = -1;
void proto_register_foo(void) {
...
{ &hf_foo_flags_first,
{ "FOO first flag", "foo.hdr.flags.first",
FT_BOOLEAN, FT_INT8,
NULL, FOO_FIRST_FLAG,
NULL, HFILL }
},
{ &hf_foo_flags_second,
{ "FOO second flag", "foo.hdr.flags.second",
FT_BOOLEAN, FT_INT8,
NULL, FOO_SECOND_FLAG,
NULL, HFILL }
},
{ &hf_foo_flags_onemore,
{ "FOO onemore flag", "foo.hdr.flags.onemore",
FT_BOOLEAN, FT_INT8,
NULL, FOO_ONEMORE_FLAG,
NULL, HFILL }
}
...
}
static void dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
...
proto_tree_add_item(foo_tree, hf_foo_hdr_flags, tvb, offset, 1, FALSE);
proto_tree_add_item(foo_tree, hf_foo_flags_first, tvb, offset, 1, FALSE);
proto_tree_add_item(foo_tree, hf_foo_flags_second, tvb, offset, 1, FALSE);
proto_tree_add_item(foo_tree, hf_foo_flags_onemore, tvb, offset, 1, FALSE); offset += 1;
}
Так как флаг - это один бит информации со значениями «1» или «0», то используется тип FT_BOOLEAN. Также задана маска для каждого флага шестым параметром (FOO_FIRST_FLAG, FOO_SECOND_FLAG, FOO_ONEMORE_FLAG), чтобы определить, какой бит из байта интерпретировать.
1.3. Правила использования программно подключаемых модулей WireShark
Перед тем как начать писать программно подключаемый модуль, необходимо произвести настройку среды разработки программно подключаемого модуля.
Установка дополнительных программных компонентов.
1. Установка программного продукта Visual C++.
2. Установка ПО Platform SDK Server 2003 R2.
3. Установка ПО Cygwin. Cygwin - UNIX-подобная среда и интерфейс командной строки для Microsoft Windows. Cygwin обеспечивает тесную интеграцию Windows приложений, данных и ресурсов с приложениями, данными и ресурсами UNIX-подобной среды.
4. Установка языка Python.
5. Так же необходимо наличие исходных файлов ПО WireShark, которые находятся в открытом доступе на официальном сайте ПО WireShark.
6. Настройка параметров в файле config.nmake, который находится в исходных файлах ПО WireShark и предназначен для настроек сборки проекта. В файле config.nmake нужно выбрать версию используемого компилятора.
7. Подготовка командной строки cmd.exe. После запуска cmd.exe необходимо вызвать пакетные файлы SetEnv.Cmd и vcvars32.bat.
8. Проверка инструментария. Командой Nmake -f Makefile.nmake verify_tools выполняется проверка наличия всех необходимых инструментов.
9. Установка библиотек. Выполняется командой nmake -f Makefile.nmake setup.
10. Сборка WireShark. Производится командой nmake -f Makefile.nmake all.
После настройки окружения можно приступить к сборке программно подключаемого модуля. Для выполнения сборки программно подключаемого модуля необходимы следующие файлы.
1. Makefile.am - UNIX/Linux make файл.
2. Makefile.common - общий make файл для UNIX/Linux и Windows, содержит имена файлов программно подключаемого модуля.
3. Makefile.nmake - make файл для Windows.
4. moduleinfo.h - содержит версию программно подключаемого модуля.
5. moduleinfo.nmake - содержит информацию о версиях DLL для Windows.
6. packet-myprotocol.c - исходный код для диссектора.
Сборка программно подключаемого модуля выполняется командой nmake -f Makefile.nmake all.
Выводы по главе 1
В первой главе были рассмотрены возможности ПО WireShark, а так же правила разработки программно подключаемых модулей и правила их использования. Это позволило получить представление о принципах работы ПО WireShark и знания о функциональном наборе, которым должен обладать разрабатываемый программно подключаемый модуль.
Изучение правил подключения программных модулей позволило сделать вывод о необходимости наличия дополнительного ПО, а именно ПО Platform SDK Server 2003 R2 и ПО Cygwin.
ГЛАВА 2. Программное обеспечение визуализации сообщений модема sierra mc7710
2.1 Интерфейс программного модуля СПО QXDM Professional
wireshark сообщение модем sierra
СПО QXDM Professional - это многофункциональный диагностический монитор, который обладает инструментами обработки событий, журналирования, отладки сообщений и диагностики команд модемов различных производителей.
Рис. 2.1. Интерфейс СПО QXDM Professional
СПО QXDM Professional позволяет сохранять сообщения, полученные от устройства в отдельный файл, с которым в дальнейшем можно работать при помощи специальных СОМ интерфейсов, предоставляемых СПО QXDM Professional.
Рис. 2.2. Рабочая область СПО QXDM Professional
Сообщение полученное от устройства разбивается на составляющие: Type - тип сообщения, Name - имя сообщения, Timestamp - временная метка пришедшего сообщения, Summary - содержание сообщения.
Так же СПО QXDM Professional предоставляет возможность просмотреть полученное сообщение в шестнадцатеричном формате.
Рис. 2.3. Сообщение в шестнадцатеричном формате
СПО QXDM Professional предоставляет COM интерфейсы для работы с файлами, хранящие элементы (item). COM-интерфейсы грубо можно разделить на пять модулей.
Модуль QXDM - автоматизация QXDM COM-интерфейса, который существовал и поставляется в QXDM до версии 03.05.50. Предполагается, что поддержка некоторых из интерфейсов будет осуществляться в течение долгого времени.
Модуль Client - предоставляет средства для объединения QXDM элементов (данные, полученные от устройства и внутренние данные, обработанные QXDM) в специальные структуры, также обеспечивает прямой доступ к QXDM элементам.
Модуль Client Config - предоставляет средства для настройки элементов конкретных типов, т.е. клиент определяет форму представления элементов.
Модуль Item - интерфейс к конкретному объекту, управляемый QXDM.
Модуль Field - предоставляет доступ к базе данных QXDM, анализирует поля определенного элемента.
Таблица 2.1
COM интерфейс программы QXDM Professional
№ пп. |
Название |
Типы аргументов |
Описание |
|
1 |
2 |
3 |
4 |
|
1. |
LoadItemStore() |
BSTR |
Позволяет загрузить хранилище элементов, находящихся в файле с расширением isf |
|
2. |
GetItemCount() |
ULONG |
Получает количество элементов в файле |
|
3. |
GetItem() |
ULONG |
Получает текущий элемент |
|
4. |
GetItemTimestampText() |
VARIANT_BOOL |
Получает временную метку текущего элемента |
|
5. |
GetItemTypeText() |
Функция позволяет получить тип элемента. |
||
6. |
GetItemKeyText () |
Функция позволяет извлечь ключ элемента. |
||
7. |
GetItemName () |
Функция позволяет получить имя элемента. Функция не имеет аргументов и возвращает значение BSTR |
||
8. |
GetItemNameSummary() |
Функция позволяет извлечь краткое описание элемента. Функция не принимает аргументов и возвращает значение BSTR. |
||
9. |
GetItemParsedText () |
Функция позволяет извлечь обработанный текст элемента. Функция не принимает аргументов и возвращает значение BSTR |
||
10. |
GetItemBuffer () |
VARIANT_BOOL |
Функция позволяет получить буфер текущего элемента. |
2.2 Программное обеспечение, реализующее визуализацию сообщений модема Sierra MC7710
СПО QXDM сообщения модема Sierra MC7710 сохраняет в файл с расширением .isf. Для обработки файла СПО QXDM предоставляется COM интерфейс реализованный в виде библиотеки CoreAutomation.dll.
Программа isfreader представленная в приложении 1 позволяет обрабатывать файлы с расширением isf и извлекать сообщения полученные от модема Sierra MC7710.
Программа isfreader загружает файл с сообщениями с помощью функции LoadItemStore(). Затем в цикле программа получает описатель элемента содержащего сообщение и дополнительную информацию с помощью функции GetItem(). Из описателя элемента извлекаются поля сообщения посредством методов GetItemTypeText() - тип элемента, GetItemKeyText() - ключ элемента, GetItemName() - имя элемента, GetItemSummary() - содержание элемента. Извлеченные данные передаются элементу tableview, который формирует представление элементов в форме таблицы.2.3 Программное обеспечение, реализующее визуализацию сообщений модема Sierra MC7710 для программы WireShark
Программное средство WireShark позволяет визуализировать данные, полученные не только с сетевого устройства, но и данные содержащиеся в локальных файлах. В связи с этим обработка данных в первом и во втором случаях отличается. В первом случае при поступлении данных из сети программа WireShark вызывает соответствующий диссектор. Вызванный диссектор осуществляет обработку и визуализацию полученных данных. Во втором случае для открытия файлов существует специальная библиотека Wiretap, на данный момент библиотека поддерживает большое количество форматов и постоянно пополняется.
Сообщения модема Sierra MC7710 после обработки СПО QXDM Professional можно сохранить в файл с расширением isf(item store file).Данный формат файла ПО WireShark не поддерживается. Для добавления возможности работать с новыми форматами файлов возможны 2 способа [4].
1. Добавить поддержку формата файла в библиотеку Wiretap.
2. Разработать внешний конвертор, преобразующий isf файл в поддерживаемый формат ПО WireShark.
Чтобы добавить поддержку нового формата файла в библиотеку нужно описать процедуру открытия, которая проверяет магическое число файла и определяет начало пакета, а также описать процедуру чтения, которая будет выделять пакеты из файла и снабжать их заголовками. В данном случае отдельным пакет будет служить отдельное сообщение обработанное СПО QXDM. Чтобы иметь возможность проверять магическое число файла или иным образом проверять формат файла должна быть известна структура файла. Для выделения пакетов из файла должен быть известен размер сообщения, а так же для выделения полей сообщения должно быть известно их смещение относительно начала сообщения. В связи с этим должна быть известна структура файла. Так как структура файла isf является закрытой [5] произвести чтение файла стандартными средствами нет возможности, потому что для добавления возможности обработки нового формата файла нужно знание о реализации файла [4].
Для реализации внешнего конвертора (пункт 2) необходимо использовать библиотеку CoreAutomation.dll с помощью которой можно будет извлечь необходимые поля из файла, затем извлеченную информацию снабдить заголовком и отправить на заданный порт по протоколу udp или tcp.
Сообщение модема Sierra MC7710 после обработки СПО QXDM Professional имеет следующие поля (назначение которых описано в п.2.1).
Type |
Key |
Item Name |
Summary |
Рис. 5. Сообщение модема Sierra MC7710 после обработки СПО QXDM
Каждое сообщение, извлеченное из файла, необходимо снабдить заголовком со следующими полями.
Размер поля Type |
Размер поля Key |
Размер поля Item Name |
Размер поля Summary |
Рис. 6. Заголовок сообщения модема Sierra MC7710
Поля псевдозаголовка позволят вычислить необходимое смещение в пакете для диссектора.
Соответственно, предварительно должен быть разработан диссектор способный обрабатывать пакеты, полученные от конвертора.
Рис. 7. Работа конвертора для isf файла
2.4 Тестирование разработанной программы isfreader
Для тестирования программы isfreader будет использован файл «10-23.16-25.isf», который содержит сообщения модема Sierra MC7710. В результате тестирования должны быть получены такие же данные, как и после обработки СПО QXDM.
Рис. 2.2. Результат работы программы QXDM Professional
Рис. 2.3. Результат работы программы isfreader
Данные полученные в результате работы программы QXDM Professional и данные полученные в результате работы программы isfreader совпадают.
Выводы по главе 2
Во второй главе был изучен интерфейс СПО QXDM Professional и COM интерфейсы которые с ним поставляются, что позволило разработать программу isfreader способную обрабатывать файлы, полученные в результате работы СПО QXDM Professional, а также стало известно что невозможно реализовать интеграцию разработанного ПО в качестве программно подключаемого модуля WireShark, потому что реализация файла isf является закрытой. Библиотека CoreAutomation.dll позволяет извлечь сообщения из isf файл без знания структуры файла, но передать эти сообщения на обработку соответствующему диссектору с помощью библиотеки wiretap нет возможности. Для реализации этой возможности необходимо, чтобы в библиотеке wiretap была возможность ручного формирования пакета.
Заключение
В ходе выполнения курсовой работы были решены следующие задачи:
- освоены правила разработки и подключения программных модулей WireShark;
- изучен интерфейс программного модуля СПО QXDM Professional;
- разработана программа, реализующая визуализацию сообщений модема Sierra MC7710, включая отображение специальной информации, полученной после обработки сообщений программным модулем СПО QXDM Professional;
- исследована возможность интеграции разработанной программы в виде программного модуля WireShark.
В результате исследования было выяснено, что не существует возможности интеграции разработанного ПО в качестве программно подключаемого модуля ПО WireShark, реализующего визуализацию сообщений модема Sierra MC7710. Чтобы реализовать данный функционал в ПО WireShark необходимо добавить поддержку работы с isf файлом, в котором содержатся сообщения модема. Для реализации данной возможности должна быть известна структура файла, а именно должно быть известно магическое число файла (если оно присутствует в нем), смещение в файле, с которого начинаются сообщения модема и размер полей сообщения, чтобы иметь возможность выделить нужное поле сообщения. Данных проблем можно избежать, если в библиотеке wiretap будет возможность формировать поля пакета самостоятельно.
ЛИТЕРАТУРА
1. Пользовательская документация //http://www.wireshark.org/docs/wsug_html_chunked/ChapterUsing.html.
2. Creating Your Own Custom Wireshark Dissector //http://www.codeproject.com/Articles/19426/Creating-Your-Own-Custom-Wireshark-Dissector
3. Пишем плагин-диссектор для Wireshark //http://habrahabr.ru/post/121990/#anch04//.
4. Packet Input //http://wiki.wireshark.org/Development/PacketInput
5. Interface Control Documents //http://www.qualcomm.com/solutions/testing/interface-control-documents
Приложение 1. Листинг программы isfreader
Листинг П1.1
/**********************************************************************
*Файл qt.ui *
*Предназначен для описания объектов классов отвечающих за визуализацию* *информации. *
*Автор : Филатов А. В., 2013 г. *
**********************************************************************/
#ifndef UI_QT_H
#define UI_QT_H
#include <QtCore/QVariant>
#include <QtGui/QAction>
#include <QtGui/QApplication>
#include <QtGui/QButtonGroup>
#include <QtGui/QHeaderView>
#include <QtGui/QMainWindow>
#include <QtGui/QMenuBar>
#include <QtGui/QStatusBar>
#include <QtGui/QTableView>
#include <QtGui/QToolBar>
#include <QtGui/QWidget>
QT_BEGIN_NAMESPACE
class Ui_qtClass
{
public:
QWidget *centralWidget;
QTableView *tableView;//Создание объекта класса предназначенного для формирования таблицы
QMenuBar *menuBar;
QToolBar *mainToolBar;
QStatusBar *statusBar;
void setupUi(QMainWindow *qtClass)
{
if (qtClass->objectName().isEmpty())
qtClass->setObjectName(QString::fromUtf8("qtClass"));
qtClass->resize(1355, 738);
centralWidget = new QWidget(qtClass);
centralWidget->setObjectName(QString::fromUtf8("centralWidget"));
tableView = new QTableView(centralWidget);
tableView->setObjectName(QString::fromUtf8("tableView"));
tableView->setGeometry(QRect(0, 0, 1351, 681));
qtClass->setCentralWidget(centralWidget);
menuBar = new QMenuBar(qtClass);
menuBar->setObjectName(QString::fromUtf8("menuBar"));
menuBar->setGeometry(QRect(0, 0, 1355, 21));
qtClass->setMenuBar(menuBar);
mainToolBar = new QToolBar(qtClass);
mainToolBar->setObjectName(QString::fromUtf8("mainToolBar"));
qtClass->addToolBar(Qt::TopToolBarArea, mainToolBar);
statusBar = new QStatusBar(qtClass);
statusBar->setObjectName(QString::fromUtf8("statusBar"));
qtClass->setStatusBar(statusBar);
retranslateUi(qtClass);
QMetaObject::connectSlotsByName(qtClass);
} // setupUi
void retranslateUi(QMainWindow *qtClass)
{
qtClass->setWindowTitle(QApplication::translate("qtClass", "qt", 0, QApplication::UnicodeUTF8));
#ifndef QT_NO_TOOLTIP
tableView->setToolTip(QApplication::translate("qtClass", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:'Segoe UI'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><br /></p></body></html>", 0, QApplication::UnicodeUTF8));
#endif // QT_NO_TOOLTIP
} // retranslateUi
};
namespace Ui {
class qtClass: public Ui_qtClass {};
} // namespace Ui
QT_END_NAMESPACE
#endif // UI_QT_H
Листинг П1.2
/*************************************************************************Файл qt.cpp *
*Работа с isf файлом, извлечение из него сообщений и вывод полей *
*сообщений в виде таблицы с помощью класса QTable. Описание работы меню,* *в частности открытие файла. *
*Автор : Филатов А. В., 2013 г. *
************************************************************************/
#include "qt.h"
//Подключение библиотеки предоставляемой СПО QXDM Professional
#import "C:\\Program Files (x86)\\Qualcomm\\QXDM\\Bin\\CoreAutomation.dll"
qt::qt(QWidget *parent, Qt::WFlags flags)
: QMainWindow(parent, flags)
{
ui.setupUi(this);
//Инициализация СОМ объекта
HRESULT hr = CoInitialize( 0 );
//Создание действий
openAction = new QAction(tr("&Open"), this);
exitAction = new QAction(tr("E&xit"), this);
connect(openAction, SIGNAL(triggered()), this, SLOT(open()));
connect(exitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
fileMenu = menuBar()->addMenu(tr("&File"));
fileMenu->addAction(openAction);
fileMenu->addSeparator();
fileMenu->addAction(exitAction);
}
/*************************************************************************Метод класса: *
*Open *
*Описание: *
*Открытие нового файла. Вывод информации в виде таблицы. *
*Параметры: *
*Нет *
*Возвращаемое значение: *
*Нет *
************************************************************************/
void qt::open()
{
//запрос у пользователя имени файла
QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), "",
tr("Item store file (*.isf)"));
if (fileName != "")
{
DMCoreAutomation::IItemStoreFilesPtr pISF(
__uuidof( DMCoreAutomation::ItemStoreFiles ) );
ULONG hISF = pISF->LoadItemStore( fileName.toLocal8Bit().data() );
ULONG itemCount = pISF->GetItemCount( hISF );
QStandardItemModel *model = new QStandardItemModel(itemCount,5,this);
//Формирование столбцов Type
model->setHorizontalHeaderItem(0, new QStandardItem(QString("Type")));//Формирование столбца Type
model->setHorizontalHeaderItem(1, new QStandardItem(QString("Key")));
model->setHorizontalHeaderItem(2, new QStandardItem(QString("Item Name")));
model->setHorizontalHeaderItem(3, new QStandardItem(QString("Summary")));
model->setHorizontalHeaderItem(4, new QStandardItem(QString("Hex")));
BSTR raw_buffer;//Переменная,которая будет хранить шестнадцетеричный формат сообщения
//Заполнение таблицы
for (ULONG i = 0; i < itemCount; i++)
{
//Получение элемента(извлечение сообщения)
DMCoreAutomation::IColorItemPtr pItem = pISF->GetItem( hISF, i );
//Извлечение полей сообщения
_bstr_t tsTxt = pItem->GetItemTimestampText( VARIANT_TRUE, VARIANT_TRUE );
_bstr_t itTxt = pItem->GetItemTypeText();
_bstr_t ikTxt = pItem->GetItemKeyText();
_bstr_t inTxt = pItem->GetItemName();
_bstr_t isTxt = pItem->GetItemSummary();
//Запись шестнадцетиричного значения сообщения
raw_buffer = pItem->GetItemBufferText(VARIANT_TRUE);
//Преобразование из BSTR в WString
std::wstring intermediateString(raw_buffer, SysStringLen(raw_buffer));
QString finalString = QString::fromStdWString(intermediateString);
//Запись полученых полей сообщения в таблицу
QStandardItem *firstColumn = new QStandardItem(QString(itTxt));
QStandardItem *secondColumn = new QStandardItem(QString(ikTxt));
QStandardItem *thirdColumn = new QStandardItem(QString(inTxt));
QStandardItem *foursColumn = new QStandardItem(QString(isTxt));
QStandardItem *fivesColumn = new QStandardItem(QString(finalString));
model->setItem(i,0,firstColumn);
model->setItem(i,1,secondColumn);
model->setItem(i,2,thirdColumn);
model->setItem(i,3,foursColumn);
model->setItem(i,4,fivesColumn);
ui.tableView->setModel(model);
}
//Закрытие файла
pISF->CloseItemStore( hISF );
}
}
void qt::quit()
{
}
qt::~qt()
{
}
Листинг П1.3
/*************************************************************************Файл qt.h *
*Создание класса приложения.Описание меню File. *
* Автор : Филатов А. В., 2013 г. *
************************************************************************/
#ifndef QT_H
#define QT_H
#include <QtGui/QMainWindow>
#include "ui_qt.h"
#include <QStandardItemModel>
#include <QTextEdit>
#include <QFileDialog>
#include <QMessageBox>
#include <QTextStream>
class qt : public QMainWindow
{
Q_OBJECT
public:
qt(QWidget *parent = 0, Qt::WFlags flags = 0);
~qt();
private:
Ui::qtClass ui;
//Создание действий
QAction *exitAction;//Действие для закрытия приложения
QAction *openAction;//Действие для открытия файла
QMenu *fileMenu;
//Объявление слотов,которые будут открывать и завершать программу
private slots:
void open();//Слот для открытия файла
void quit();//Слот для закрытия приложения
};
#endif // QT_H
Листинг П1.4
/*************************************************************************Файл main.cpp. *
*Отображение основного окна приложения. *
* Автор : Филатов А. В., 2013 г. *
************************************************************************/
#include "qt.h"
#include <QtGui/QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
qt w;
w.show();
return a.exec();
}
Листинг плагина WireShark
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <epan/packet.h>
#define FOO_PORT 35000
/* Номер UDP порта, на котором мы предполагаем будет находится FOO траффик. */
static int proto_foo = -1;
/* При регистрации протокола переменная затрется идентификатором протокола. */
static gint ett_foo = -1;
static int type = -1;//Байт отвечающий за длинну поля type
static int key = -1;
static int iname = -1;
static int summary = -1;
guint8 sT = 0;//длинна поля type, полученная из пакета
guint8 sK = 0;
guint8 sN = 0;
guint8 sS = 0;
void proto_register_foo(void)
{
static hf_register_info hf[] = {
{ &type,
{ "Type", "foo.hdr.type",//Тип элемента
FT_STRING, BASE_NONE,
NULL, 0x0,
NULL, HFILL }
},
{ &key,
{ "Key", "foo.hdr.key",//Ключ элемента
FT_STRING, BASE_NONE,
NULL, 0x0,
NULL, HFILL }
},
{ &iname,
{ "Item name", "foo.hdr.itemname",//Имя элемента
FT_STRING, BASE_NONE,
NULL, 0x0,
NULL, HFILL }
},
{ &summary,
{ "Summary", "foo.hdr.summary",//Содержание элемента
FT_STRING, BASE_NONE,
NULL, 0x0,
NULL, HFILL }
}
};
static gint *ett[] = { &ett_foo };
proto_foo = proto_register_protocol (
"FOO Protocol", /* полное имя */
"FOO", /* короткое имя */
"foo" /* аббревиатура */
);
proto_register_field_array(proto_foo, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
}
static void dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
col_set_str(pinfo->cinfo, COL_PROTOCOL, "FOO");
col_clear(pinfo->cinfo, COL_INFO);
if (tree) {
proto_item *ti = NULL;
proto_tree *foo_tree = NULL;
ti = proto_tree_add_item(tree, proto_foo, tvb, 0, -1, FALSE);
foo_tree = proto_item_add_subtree(ti, ett_foo);
sT = tvb_get_guint8(tvb, 0);//Извлекаем из пакета длину поля type
sK = tvb_get_guint8(tvb, 1);
sN = tvb_get_guint8(tvb, 2);
sS = tvb_get_guint8(tvb, 3);
proto_tree_add_item(foo_tree, type, tvb, 4, sT, FALSE);
proto_tree_add_item(foo_tree, key, tvb, sT + 4, sK,FALSE);
proto_tree_add_item(foo_tree, iname, tvb, sT + 4 + sK, sN, FALSE);
proto_tree_add_item(foo_tree, summary, tvb, sT + 4 + sK + sN, sS, FALSE);
}
}
void proto_reg_handoff_foo(void)
{
static dissector_handle_t foo_handle;
foo_handle = create_dissector_handle(dissect_foo, proto_foo);
dissector_add_uint("udp.port", FOO_PORT, foo_handle);
}
Листинг программы отправляющий пакеты по придуманному протоколу
«FOO».Предварительно установить адаптер замыкания на себя
// SocketClient.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <winsock2.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <conio.h>
#include <iostream>
using namespace std;
#import "C:\\Program Files (x86)\\Qualcomm\\QXDM\\Bin\\CoreAutomation.dll"
#define DEFAULT_PORT 35000//Порт FOO
int main(int argc, char **argv) {
cout << "File name-> ";
char fname[256];
cin >> fname;
cout << endl;
// Initialize COM library
HRESULT hr = CoInitialize( 0 );
if (FAILED( hr ))
{
_tprintf_s( _T("Error: Failed to initialize COM library\n") );
return -1;
}
// Initialize QXDM interface
DMCoreAutomation::IItemStoreFilesPtr pISF(
__uuidof( DMCoreAutomation::ItemStoreFiles ) );
if (pISF == 0)
{
_tprintf_s( _T("Error: Failed to initialize ISF interface\n") );
return -1;
}
// Load ISF file
ULONG hISF = pISF->LoadItemStore( fname );
if (hISF == 0xFFFFFFFF)
{
_tprintf_s( _T("Error: Failed to load input ISF: %s\n"), fname );
return -1;
}
char Buffer[8192];
char *server_name= "192.168.43.23";
char server_addr[20];
unsigned short port = DEFAULT_PORT;
int retval, loopflag=0;
unsigned int addr;
int socket_type = SOCK_DGRAM;
struct sockaddr_in server;
struct hostent *hp;
WSADATA wsaData;
SOCKET conn_socket;
char foobuf[210];
ULONG itemCount = pISF->GetItemCount( hISF );
if ((retval = WSAStartup(0x202,&wsaData)) != 0) {//инициализация библиотеки Winsock
fprintf(stderr,"WSAStartup failed with error %d\n",retval);
WSACleanup();
return -1;
}
if (isalpha(server_name[0]))
{ /* server address is a name */
hp = gethostbyname(server_name);
}
else
{ /* Convert nnn.nnn address to a usable one */
addr = inet_addr(server_name);
hp = gethostbyaddr((char *)&addr,4,AF_INET);
}
if (hp == NULL )
{
fprintf(stderr,"Client: Cannot resolve address [%s]: Error %d\n",
server_name,WSAGetLastError());
WSACleanup();
exit(1);
}
//
// Copy the resolved information into the sockaddr_in structure
//
memset(&server,0,sizeof(server));
memcpy(&(server.sin_addr),hp->h_addr,hp->h_length);
server.sin_family = hp->h_addrtype;
server.sin_port = htons(port);
conn_socket = socket(AF_INET,socket_type,0); /* Open a socket */
if (conn_socket <0 ) {
fprintf(stderr,"Client: Error Opening socket: Error %d\n",
WSAGetLastError());
WSACleanup();
return -1;
}
cout << "Start" << endl << "-----------------------------------------------------"<<endl;
if (connect(conn_socket,(struct sockaddr*)&server,sizeof(server))//Соединение
== SOCKET_ERROR) {
system("cls");
fprintf(stderr,"connect() failed: %d\n",WSAGetLastError());
getch();
WSACleanup();
return -1;
}
int received = 0;//Полученние данные
int sent = 0;//Отправленные данные
//Заполнение таблицы
for (ULONG i = 0; i < itemCount; i++)
{
//Получение элемента(извлечение сообщения)
DMCoreAutomation::IColorItemPtr pItem = pISF->GetItem( hISF, i );
//Извлечение полей сообщения
_bstr_t itTxt = pItem->GetItemTypeText();
_bstr_t ikTxt = pItem->GetItemKeyText();
_bstr_t inTxt = pItem->GetItemName();
_bstr_t isTxt = pItem->GetItemSummary();
char type[30];
char name[256];
char key[30];
char sum[256];
strcpy_s(type,(char *) itTxt);
strcpy_s(key,(char *) ikTxt);
strcpy_s(name,(char *) inTxt);
strcpy_s(sum,(char *) isTxt);
cout << "Type->" << type <<endl;
cout << "Key->" << key <<endl;
cout << "Item name->" << name <<endl;
cout << "Summary->" << sum <<endl;
cout << "-----------------------------------------------------"<<endl;
string s;
string res;
res = strlen(type);//size type
res += strlen(key);//size key
res += strlen(name);//size name
res += strlen(sum);//size sum
s.assign(type,strlen(type));
res +=s;
s.assign(key,strlen(key));
res += s;
s.assign(name,strlen(name));
res += s;
s.assign(sum,strlen(sum));
res += s;//строка,которая будет передана
//содержание пакета: (длина поля тип,длинна поля ключ,
//длина поля имя элемента,длина поля содержание элемента,
//сами type,key,item name,summary,
retval = send(conn_socket,res.c_str(),strlen(res.c_str()),0);
if (retval == SOCKET_ERROR) {
system("cls");
fprintf(stderr,"send() failed: error %d\n",WSAGetLastError());
getch();
WSACleanup();
return -1;
}
sent += retval;
printf("Sent %d bytes to server. Received %d bytes from server\r\n", sent, received);
s = "";
res = "";
Sleep(2000);
}
//Закрытие файла
pISF->CloseItemStore( hISF );
closesocket(conn_socket);
WSACleanup();
}
Размещено на Allbest.ru
Подобные документы
Внутренние и внешние модемы: отличительные характеристики. Устройство модема, способы модуляции, используемые в модемной связи. Осуществление передачи данных посредством модема. Интерфейс модема, первоначальная настройка и стpуктуpа команды набоpа номеpа.
дипломная работа [65,6 K], добавлен 19.03.2010Основные требования к составу и параметрам технических средства. Верификация программного продукта. Расширение функционала программы и его реализация. Отладка и тестирование программного продукта. Тестирование программы в граничных и реальных условиях.
курсовая работа [1,3 M], добавлен 29.12.2014Требования, предъявленные к полноценному локальному чату. Протокол передачи данных TCP. Описание программы сервера. Этапы разработки программного продукта. Функция приема сообщений от сервера. Принятие и отправка сообщений всем пользователям чата.
курсовая работа [447,0 K], добавлен 21.01.2016Сравнительный анализ программ-аналогов, характеристика инструментальных средств разработки. Анализ требований и определение спецификаций программного обеспечения, отладка и тестирование программы. Изучение руководства по использованию программы.
курсовая работа [2,1 M], добавлен 10.04.2023Обоснование выбора программно-технических средств. Надежность программы и состав технических средств. Разработка структурной схемы программы, алгоритмического и программного интерфейса. Технология разработки интерфейса пользователя и программных модулей.
дипломная работа [3,2 M], добавлен 22.01.2013Программа для выбираемой единицы измерения (градусы Фаренгейта или Цельсия) и для задаваемого значения температуры в этой единице измерения. Среда Delphi. Системные требования. Блок схема программы. Интерфейс. Тестирование и сопровождение программы.
курсовая работа [447,6 K], добавлен 04.02.2009Методика и основные этапы создания многофункциональной программы получения и отправки сообщений по локальной сети с помощью программного обеспечения Winpopup и Traypopup. Сравнительная характеристика встроенных протоколов и их функциональные особенности.
дипломная работа [371,6 K], добавлен 19.06.2010Стадии разработки программного средства. Средства, методологии и методы его разработки. Оценка надежности и качества проекта. Обоснование необходимости разработки программы. Тестирование как процесс выполнения тестовой программы с намерением найти ошибки.
презентация [57,0 K], добавлен 27.12.2013Применение программного обеспечения для разработки игры "Быки и коровы". Описание алгоритма и интерфейса пользователя программы. Назначение и область применения и описание возможностей программы. Рассмотрение списка сообщений об ошибках программы.
курсовая работа [799,2 K], добавлен 26.04.2021Выбор базовых программных средств для разработки оригинального программного обеспечения. Компоненты программно-методического комплекса проектирования токарных операций. Программное обеспечение для организации интерфейса программно-методического комплекса.
дипломная работа [2,8 M], добавлен 14.05.2010