Изучение методов разработки программного обеспечения для создания UDP сокетов и протоколов
Курсовой проект - Компьютеры, программирование
Другие курсовые по предмету Компьютеры, программирование
mName);
// Необходимо определить список адресов, на которые
// будем посылать UDP пакеты. addrs = null;
if(room != null) {
// Если сообщение адресовано в конкретную комнату, то
// выделяем список тех, кто в ней находится.= room.getAddresses();
} else {
// Иначе устанавливаем список в широковещательный.= BROADCAST;
}
// Последовательно в цикле передаём пакет по всем нужным адресам.(String addr : addrs) {
// Преобразование адреса из символьного представления в
// понятный программе.inetAddr = InetAddress.getByName(addr);
// Пропускаем передачу пакета к себе же.
if(inetAddr.getHostAddress().equals(localAddress))
continue;
// Формируем UDP пакет для передчи. Методу передаются сообщение
// в виде байтового массива, длина сообщения, сетевой адрес
// назначения, а также порт.= new DatagramPacket(message.getBytes(), message.length(),
inetAddr, port);
// Отсылаем пакет через сокет.
sendingSocket.send(packet);
}
} catch (SocketException e) {.printStackTrace();
} catch (UnknownHostException e) {.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
Перед отправкой сообщения, оно формируется таким способом, чтобы было понятно другим подобным программам клиентам. Этим формированием занимается метод prepareMessage(), описанный ниже:
/**
* Данный метод предназначен для подготовки сообщения к
* передачи в зависимости от его типа.
*
* @param message сообщение для передачи. Может быть null
* при типах сообщения отличных от CMD_MESSAGE.
* @param roomName комната, в которую необходимо передать сообщение.
* Может быть null, тогда сообщение будет передано широковещательно.
* @param type тип сообщения.
* @return подготовленнное к передаче сообщение.
*/String prepareMessage(String message, String roomName, String type) {mes = null;
// Тип сообщения CMD_PRESENT
// Пример: PRSN:nick(type.equals(CMD_PRESENT)) {
// Добавляем к идентификатору ник пользователя.
mes = CMD_PRESENT+":"+nick;
}
// Тип сообщения CMD_SYNC
// Пример: SYNC:room_1:@room_2...if(type.equals(CMD_SYNC)) {
mes = CMD_SYNC;
// Добавляем к идентификатору список всех комнат,
// в которых находится пользователь.(NetRoom r : rooms)+= ":"+r.getName();
}
// Тип сообщения CMD_NICK
// Пример: NICK:nickif(type.equals(CMD_NICK)) {
// Добавляем к идентификатору ник пользователя.= CMD_NICK+":"+nick;
}
// Тип сообщения CMD_QUIT
// Пример: QUITif(type.equals(CMD_QUITE)) {= CMD_QUITE;
}
// Тип сообщения CMD_SYNC
// Пример: MSG:room:messageif(type.equals(CMD_MESSAGE)) {room = getRoomByName(roomName);(room != null) {
// Если у комнаты стоит идентияикатор защищённого соединения,
// то сообщение перед отправкой необходимо зашифровать.(room.isProtected()) {
// Проверяем, пришёл ли к нам открытые ключ от инициатора
// защищённого соединения.(room.getExternalPublicKey() != null) {
// Зашифровываем сообщение с помощтю полученного открытого ключа.
message = RSACipher.encode(message, room.getExternalPublicKey());
} else {
// Если кдюча нет, то посылаем в представление сообщение об ошибке.
// Пример: from:INFO:room:message(localAddress
+":"+INFO
+":"+room.getName()
+":"+"Ошибка при кодировании. Нет открытого ключа.");"";
}
}
}
// Добавляем к идентификатору название комнаты,
// в которую оно адресовано, и само сообщение.
mes = CMD_MESSAGE+":"+roomName+":"+message;
}
// Тип сообщения CMD_PRV_INIT
// Пример: INIT:room:public_keyif(type.equals(CMD_PRV_INIT)) {
// Находим в спике комнат нужную по названию.
NetRoom room = getRoomByName(roomName);(room != null) {
// Извлекаем открытый ключ, который понадобится другой
// стороне защищенного соединения для шифрования исходящих
// сообщений.pubKey = room.getKeyPair().getPublic();
// Добавляем к идентификатору название комнаты, в которую
// адресовано ообщение и открытый ключ.
mes = CMD_PRV_INIT+":"+roomName+":"+new String(pubKey.getEncoded());
}
}
// Тип сообщения CMD_ACCEPT
// Пример: ACPT:room:public_keyif(type.equals(CMD_PRV_ACCEPT)) {
// К идентификатору добавляем название комнаты,
// в которой устанавливается защищённое соединение,
// а также само сообщение.= CMD_PRV_ACCEPT+":"+roomName+":"+message;
}mes;
}
После приёма входящего сообщения, его необходимо обработать, для этого служит метод parseMessage(), описанный ниже:
/**
* Парсинг входящих сообщений.
*
* @param from сетевой адрес того, от кого пришло сообщение.
* @param mes само сообщение.
*/void parseMessage(String from, String mes) {
// PRSN:nick(mes.startsWith(CMD_PRESENT)) {
// На маячок нужно ответить синхронизирующим сообщением.
// В нём передаётся список комнат, к которым подключен пользователь.
sendMessage(null, null, CMD_SYNC);
// Передаём команду в систему отображения.
// Пример: from:PRSN:nick(from+":"+mes);
}
// SYNC:room_1:room_2...if(mes.startsWith(CMD_SYNC)) {
String[] split = mes.split(":");
// В цикле перебираем все названия комнат в синхросообщении.
for(int i = 1; i < split.length; i++) {
// Находим нужную комнату.room = getRoomByName(split[i]);
// Добавляем в список адресов комнаты тот,
// от кого пришло это сообщение.
if(room != null).addAddress(from);
}
// Передаём команду в систему отображения.
// Пример: from:SYNC:room_1:room_2...(from+":"+mes);
}
// QUITif(mes.startsWith(CMD_QUITE)) {
// Передаём команду в систему отображения.
// Пример: from:QUIT(from+":"+mes);
}
// NICK:nickif(mes.startsWith(CMD_NICK)) {
// Передаём команду в систему отображения.
// Пример: from:NICK:nick(from+":"+mes);
}
// MSG:room:messageif(mes.startsWith(CMD_MESSAGE)) {[] split = mes.split(":", 3);roomName = split[1];
String message = split[2];
// Находим по имени комнату, в которую адресовано сообщение.
NetRoom room = getRoomByName(roomName);(room != null) {
// Если у комнаты стоит метка о необходимости защищённого
// соединения, то входящее сообщение неоходимо расшифровать.(room.isProtected()) {{
// Расшифровываем входящее сообщение с помощью
// сохранённого закрытого ключа.= RSACipher.decode(message, room.getKeyPair().getPrivate());
} catch (BadPaddingException e) {
// Если сл?/p>