Изучение методов разработки программного обеспечения для создания UDP сокетов и протоколов
Курсовой проект - Компьютеры, программирование
Другие курсовые по предмету Компьютеры, программирование
· сети. Передаётся списку контактов при закрытии приложения.:room:public_key - команда, обозначающая, что посылающий её клиент хочет открыть зашифрованное приватное соединение в комнате room с открытым ключом public_key.:room:public_key - этой командой должен ответить клиент в случае согласия на установление защищённого соединения в комнате room с открытым ключом public_key.:room:message - эта команда служит для передачи сообщений (message) между пользователями. Сообщение доставляется в комнату room.
Блок шифрования служит генерации ключей (открытого и закрытого), шифрования сообщений на основе открытого ключа и расшифровки сообщений на основе открытого и закрытого ключей. Подробнее об используемом в этом блоке алгоритме шифрования RSA написано в приложении А.
Контроллер служит в основном для уменьшения связности программного кода, следит за правильностью передачи событий внутри программы, своевременным обновлением отображаемых пользователю данных.
Графическое представление необходимо для отрисовки пользовательского интерфейса и отображения всех необходимых данных.
Функциональная схема шифрования с открытым ключом представлена на рисунке 3.2.
Рисунок 3.2 - Схема шифрования с открытым ключом
Алгоритм шифрования сообщения следующий:
пользователь В выбирает пару ключей (e,d) и шлёт ключ шифрования e (открытый ключ) пользователю А по открытому каналу, а ключ расшифрования d (закрытый ключ) защищён и секретен (он не должен передаваться по открытому каналу);
чтобы послать сообщение m пользователю В, пользователь А применяет функцию шифрования, определённую открытым ключом e: Ee(m) = c, c - полученный шифротекст;
пользователь В расшифровывает шифротекст c, применяя обратное преобразование Dd, однозначно определённое значением d.
4. Описание основных модулей и функций программы
Основой сетевого взаимодействия в программе является класс Network. Приведём список основных команд, на основе которых строится всё сетевое взаимодействие между клиентами программами. В классе они представлены в виде глобальных переменных:
/**
* Идентификатор команды "маячка". Передаётся для
* обозначание, что клиент в сети.
* Пример: PRSN
*/static final String CMD_PRESENT = "PRSN";
/**
* Идентификатор команды смены ника.
* Пример: NICK:nick
*/static final String CMD_NICK = "NICK";
/**
* Идентификатор команды синхронизации. В команде
* передаётся список названий всех комнат, в
* которых состоит клиент.
* Пример: SYNC:room1:room2:...
*/static final String CMD_SYNC = "SYNC";
/**
* Идентификатор команды выхода. Команда широко-
* вещательно отсылается при выходе из клиентской
* программы.
* Пример: QUIT
*/static final String CMD_QUITE = "QUIT";
/**
* Идентификатор команды инициализации защищённого
* соединения. Вместе с командой отсылается открытый
* ключ, с помощью которого будут шифроваться исходящие
* сообщения.
* Пример: INIT:public_key
*/
public static final String CMD_PRV_INIT = "INIT";
/**
* Идентификатор команды подтверждения установления
* защищённого соединения. Вместе с командой передаётся
* открытый ключ для шифровки входящих сообщений.
* Пример: ACPT:public_key
*/static final String CMD_PRV_ACCEPT = "ACPT";
/**
* Идентификатор команды входящего сообщения. Вместе
* с командой передаётся название комнаты, в которую
* адресовано сообщение, и само сообщение.
* Пример: MSG:room:message
*/static final String CMD_MESSAGE = "MSG";
Приём UDP пакетов из UDP сокета, слушающего определённый порт, организован в виде отдельной нити в программе. Эту нить запускает метод runRecievingProcess(), описание которого представлено ниже:
/**
* Данный метод запускает процесс приёма входящих
* UDP пакетов в отдельной нити.
*/void runRecievingProcess() {Thread(new Runnable() {
@Overridevoid run() {ds = null;packet = null;[] buf = new byte[BUF_LENTH];
try {
// создаём UDP совет, слушающий входящие соединения
// на порт port.= new DatagramSocket(port);
} catch (SocketException e) {.printStackTrace();
}
// Создаём пакет на основе буфера и указания его длины,
// в который будет записан входящий пакет данных.
packet = new DatagramPacket(buf, buf.length);
// Бесконечный цикл для приёма всех входящих UDP пакетов.
while(true) {{
// Принимаем UDP пакет. .receive(packet);
} catch (IOException e) {
e.printStackTrace();
}
// Т.к. буфер данных, в который записывается сообщение
// из пришедшего пакета, всегда дополняется до максимума,
// необходимо выделить из него лишь значимую часть.
byte[] shortBuf = new byte[packet.getLength()];.arraycopy(buf, 0, shortBuf, 0, packet.getLength());mes = new String(shortBuf);
// Выводим в консоль пришедшее сообщение из пакета..out.println(mes);
// Передаём сообщение и адрес, откуда оно пришло, в
// специальный метод для дальнейшего анализа данных.
parseMessage(packet.getAddress().getHostAddress(), mes);
}
}
}).start(); // Запуск нити
}
Чтобы что-то принять, нужно что-то отправить. Для отправки UDP пакетов служит методы sendMessage(), описанный ниже:
/**
* Данный метод передаёт UDP пакеты через UDP сокет.
*
* @param message сообщение для передачи. Может быть null
* при типах сообщения отличных от CMD_MESSAGE.
* @param roomName комната, в которую необходимо передать сообщение.
* Может быть null, тогда сообщение будет передано широковещательно.
* @param type тип сообщения.
*/public void sendMessage(String message, String roomName, String type) {packet = null;(type == null || (message == null && type == CMD_MESSAGE))new NullPointerException();(message == null)
message = "";{
// Подготовливаем сообщение в зависимости от его типа.
message = prepareMessage(message, roomName, type);
// Проверяем, находится ли пользователь в той комнате,
// в которую нужно передать сообщение.room = getRoomByName(roo