Создание клиент-серверного приложения
Разработка системы, базирующейся на протоколе LIMone, для обмена мгновенными сообщениями и пересылки файлов в процессе деловой переписки. Реализация системы в виде клиент-серверного приложения. Расчет экономических показателей программного продукта.
Рубрика | Программирование, компьютеры и кибернетика |
Вид | дипломная работа |
Язык | русский |
Дата добавления | 22.08.2016 |
Размер файла | 4,7 M |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
return;
}
if (!inpack.decode_header(h))
{
disconnect_form_server();
QMessageBox::critical(this, trUtf8("Ошибка"),
trUtf8("Заголовок испорчен. "
"Соединение сброшено!"));
return;
}
if (h.packtype != HEADER_PACKAGE_TYPE::GENERAL::ROOT_AUTHORIZATION)
return;
if (!inpack.decode_TLV(TLVS::OK, tlv))
{
disconnect_form_server();
if (inpack.decode_TLV(TLVS::ERRORS, tlv))
QMessageBox::critical(this, trUtf8("Авторизация администратора"),
QString::fromStdString(tlv.getString()));
else
QMessageBox::critical(this, trUtf8("Авторизация администратора"),
trUtf8("Не обнаружены поля OK|ERR"));
return;
}
conn_wgt->pb_inc();
outpack.clear();
outpack.generate_header(HEADER_PACKAGE_TYPE::CONTACT_LIST::GET_GROUP_LIST);
cnt = send_to_server(outpack, "Список групп не может быть запрошен!");
if (cnt < 0) return;
conn_wgt->pb_inc();
outpack.clear();
outpack.generate_header(HEADER_PACKAGE_TYPE::CONTACT_LIST::GET_CONTACT_LIST);
cnt = send_to_server(outpack, "Список собеседников не может быть запрошен!");
if (cnt < 0) return;
conn_wgt->pb_inc();
outpack.clear();
conn_wgt->show_buttons();
conn_wgt->close();
show();
slot_read();
connect(sock, SIGNAL(readyRead()), SLOT(slot_read()));
keep_alive->start();
}
void Widget::slot_read()
{
if (!sock->isOpen()) return;
int bytes_read;
while (sock->bytesAvailable() > 0)
{
bytes_read = read_from_server(inpack);
if (bytes_read < 0)
{
disconnect_form_server();
return;
}
if (bytes_read < HEADER_OFFSET) return;
parsePack(inpack);
}
}
void Widget::parsePack(Package &inpack)
{
HEADER h;
if (!inpack.decode_header(h)) return;
switch (h.packtype)
{
case HEADER_PACKAGE_TYPE::CONTACT_LIST::GET_GROUP_LIST:
{
TLV tlv;
if (inpack.decode_TLV(TLVS::OK, tlv))
{
loaded_groups++;
if (loaded_groups == 2) emit readyContactList();
return;
}
Group p;
if (!inpack.read_group_info(p)) return;
foreach (Group grp, GroupList)
if (grp.GroupID == p.GroupID) return;
GroupList.append(p);
return;
}
case HEADER_PACKAGE_TYPE::CONTACT_LIST::GET_CONTACT_LIST:
{
TLV tlv;
if (inpack.decode_TLV(TLVS::OK, tlv))
{
loaded_groups++;
if (loaded_groups == 2) emit readyContactList();
return;
}
Contact p;
if (!inpack.read_user_info_with_status(p)) return;
foreach (Contact cont, ContactList)
if (cont.UIN == p.UIN) return;
ContactList.append(p);
return;
}
case HEADER_PACKAGE_TYPE::AUTHORIZATION::CHANGE_USER_STATUS:
{
string uin;
STATUS status;
string status_text;
TLV tlv;
if (inpack.decode_TLV(TLVS::UIN, tlv)) uin = tlv.getString();
else return;
if (inpack.decode_TLV(TLVS::STATUS, tlv))
status = tlv.getUIntN<STATUS>();
else return;
if (inpack.decode_TLV(TLVS::STATUS_TEXT, tlv))
status_text = tlv.getString();
else status_text = string();
for (int i = 0; i < ContactList.size(); i++)
if (ContactList.value(i).UIN == uin)
{
ContactList[i].Status = status;
ContactList[i].StatusText = status_text;
if (ContactList.value(i).reference != NULL)
{
QTreeWidgetItem* contact_item =
(QTreeWidgetItem*)ContactList.value(i).reference;
contacts_tree->setContactStatus(contact_item, status,
status_text);
}
else emit readyContactList();
return;
}
return;
}
case HEADER_PACKAGE_TYPE::AUTHORIZATION::CHANGE_USER_INFO:
{
Contact p;
if (!inpack.read_base_user_info(p)) return;
contacts_tree->correctionContact(p);
return;
}
case HEADER_PACKAGE_TYPE::CONTACT_LIST::CREATE_USER:
{
Contact p;
if (!inpack.read_base_user_info(p)) return;
p.reference = NULL;
ContactList.append(p);
contacts_tree->correctionContact(p);
return;
}
case HEADER_PACKAGE_TYPE::CONTACT_LIST::CREATE_GROUP:
{
Group p;
if (!inpack.read_group_info(p)) return;
QTreeWidgetItem* new_item = NULL;
if (p.ParentGroupID == 0)
new_item =
new QTreeWidgetItem(contacts_tree->invisibleRootItem());
else
{
for (int i = 0; i < GroupList.size(); i++)
if (GroupList.value(i).GroupID == p.ParentGroupID)
{
if (GroupList.value(i).reference == NULL) return;
new_item =
(QTreeWidgetItem*) GroupList.value(i).reference;
new_item = new QTreeWidgetItem(new_item);
break;
}
if (new_item == NULL) return;
}
p.reference = new_item;
GroupList.append(p);
new_item->setText(0, QString::fromStdString(p.Name));
new_item->setIcon(0, QPixmap(":/images/group.png"));
return;
}
}
}
bool Widget::getNeededPack(PACKTYPE packtype, Package &pack)
{
int bytes_read = 0;
HEADER h;
while (sock->bytesAvailable() > 0 || sock->waitForReadyRead())
{
bytes_read = read_from_server(pack);
if (bytes_read < HEADER_OFFSET) continue;
if (!pack.decode_header(h)) return false;
if (h.seq != 0 && h.packtype == packtype) return true;
else parsePack(pack);
}
QMessageBox::critical(this, trUtf8("Ошибка"),
trUtf8("Сервер не отвечает!"));
return false;
}
void Widget::slot_change_root_password(QString oldp, QString newp)
{
disconnect(sock, SIGNAL(readyRead()), this, SLOT(slot_read()));
keep_alive->stop();
TLV tlv;
outpack.clear();
string cipher;
string oldpass = oldp.toStdString();
RSAES_OAEP_SHA_Encryptor e(*serverPublicKey);
StringSource(oldpass, true, new PK_EncryptorFilter(rng, e,
new StringSink(cipher)));
outpack.write_TLV(TLVS::PASSWORD, cipher);
string newpass = newp.toStdString();
cipher.clear();
StringSource(newpass, true, new PK_EncryptorFilter(rng, e,
new StringSink(cipher)));
outpack.write_TLV(TLVS::NEW_PASSWORD, cipher);
outpack.generate_header(HEADER_PACKAGE_TYPE::GENERAL::CHANGE_ROOT_PASSWORD);
int cnt = send_to_server(outpack, "Невозможно "
"отправить запрос на смену пароля!");
if (cnt < 0) return;
outpack.clear();
if (getNeededPack(HEADER_PACKAGE_TYPE::GENERAL::CHANGE_ROOT_PASSWORD,
outpack))
{
if (outpack.decode_TLV(TLVS::OK, tlv))
{
QMessageBox::information(this,
trUtf8("Смена пароля администратора"),
trUtf8("Пароль заменен :)"));
chrtpass_wgt->close();
}
else
{
if (outpack.decode_TLV(TLVS::ERRORS, tlv))
QMessageBox::critical(this,
trUtf8("Смена пароля администратора"),
QString::fromStdString(tlv.getString()));
else QMessageBox::critical(this,
trUtf8("Смена пароля администратора"),
trUtf8("Не обнаружены поля OK|ERR"));
}
}
else return;
slot_read();
connect(sock, SIGNAL(readyRead()), SLOT(slot_read()));
keep_alive->start();
}
void Widget::slot_new_uin(Contact p)
{
disconnect(sock, SIGNAL(readyRead()), this, SLOT(slot_read()));
keep_alive->stop();
TLV tlv;
outpack.clear();
outpack.write_base_user_info(p);
string cipher;
RSAES_OAEP_SHA_Encryptor e(*serverPublicKey);
StringSource(p.Password, true,
new PK_EncryptorFilter(rng, e,
new StringSink(cipher)
) // PK_EncryptorFilter
); // StringSource
outpack.write_TLV(TLVS::PASSWORD, cipher);
outpack.generate_header(HEADER_PACKAGE_TYPE::CONTACT_LIST::CREATE_USER);
int cnt = send_to_server(outpack, "Невозможно "
"отправить запрос на создание UIN!");
if (cnt < 0) return;
outpack.clear();
if (getNeededPack(HEADER_PACKAGE_TYPE::CONTACT_LIST::CREATE_USER,
outpack))
{
if (outpack.decode_TLV(TLVS::OK, tlv))
newuin_wgt->close();
else
{
if (outpack.decode_TLV(TLVS::ERRORS, tlv))
QMessageBox::critical(this,
trUtf8("Создание нового пользователя"),
QString::fromStdString(tlv.getString()));
else QMessageBox::critical(this,
trUtf8("Создание нового пользователя"),
trUtf8("Не обнаружены поля OK|ERR"));
}
}
else return;
slot_read();
connect(sock, SIGNAL(readyRead()), SLOT(slot_read()));
keep_alive->start();
}
Приложение Г Исходный код клиента
Модуль widget: widget.cpp
void Widget::slot_send_message(QString UIN, GROUP_ID gid, QString mess)
{
disconnect(sock, SIGNAL(readyRead()), this, SLOT(slot_read()));
keep_alive->stop();
TLV tlv;
outpack.clear();
if (!UIN.isEmpty())
outpack.write_TLV(TLVS::UIN, UIN.toStdString());
else outpack.write_TLV(TLVS::GROUP_ID, gid);
// шифрование сообщения
byte iv[AES::BLOCKSIZE];
memset(iv, 0x00, AES::BLOCKSIZE);
string plaintext = mess.toStdString();
string ciphertext;
AES::Encryption aesEncryption(message_key, MESSAGE_KEY_SIZE);
CBC_Mode_ExternalCipher::Encryption cbcEncryption(aesEncryption, iv);
StringSource(plaintext, true,
new StreamTransformationFilter(cbcEncryption,
new StringSink(ciphertext)));
// шифр получен
outpack.write_TLV(TLVS::MESSAGE, ciphertext);
outpack.generate_header(HEADER_PACKAGE_TYPE::MESSAGES::SEND_MESSAGE);
int cnt = send_to_server(outpack, "Невозможно отправить сообщение!");
if (cnt < 0) return;
outpack.clear();
if (getNeededPack(HEADER_PACKAGE_TYPE::MESSAGES::SEND_MESSAGE, outpack))
{
if (!outpack.decode_TLV(TLVS::OK, tlv))
{
if (outpack.decode_TLV(TLVS::ERRORS, tlv))
conv_wgt->showError(UIN,
QString::fromStdString(tlv.getString()));
else
conv_wgt->showError(UIN, trUtf8("Не обнаружены поля OK|ERR"));
}
}
else return;
slot_read();
connect(sock, SIGNAL(readyRead()), SLOT(slot_read()));
keep_alive->start();
}
int FilesTransferWidget::send_to_server(Package &pack)
{
if (!sock->isOpen()) return -1;
int cnt;
if ((cnt = sock->write(pack.buffer(), pack.getPackLength())) !=
pack.getPackLength())
return -1;
return cnt;
}
void FilesTransferWidget::addFileToTransfer(QString UIN, QString FileName)
{
File2 new_fl;
new_fl.UIN_to = UIN.toStdString();
new_fl.FileName = FileName.toStdString();
new_fl.FileSize = QFile(FileName).size();
new_fl.current_part = 0;
new_fl.fd = new QFile(FileName);
if (!new_fl.fd->open(QIODevice::ReadOnly))
{
QMessageBox::critical(this, trUtf8("Ошибка"),
trUtf8("Файл не может быть открыт!"));
delete new_fl.fd;
return;
}
QTreeWidgetItem* new_item = new QTreeWidgetItem(this);
new_fl.reference = new_item;
new_item->setText(0, QFileInfo(FileName).fileName());
new_item->setIcon(0, QIcon(QPixmap(":/file-transfer/file-transfer-"
"upload.png")));
for (int i = 0; i < ContactList.size(); i++)
if (ContactList[i].UIN == new_fl.UIN_to)
{
new_item->setText(1,
QString::fromStdString(ContactList[i].Surname) +
trUtf8(" ") +
QString::fromStdString(
ContactList[i].Name).at(0) +
trUtf8(" ") +
QString::fromStdString(
ContactList[i].Patronymic).at(0));
break;
}
QToolButton *cancel_btn = new QToolButton(this);
cancel_btn->setIcon(QIcon(QPixmap(":/file-transfer/file-transfer"
"-stop.png")));
cancel_btn->setToolButtonStyle(Qt::ToolButtonIconOnly);
cancel_btn->setToolTip(trUtf8("Отменить передачу файла"));
cancel_btn->setAutoRaise(true);
connect(cancel_btn, SIGNAL(clicked()), SLOT(sendCancelFile()));
setItemWidget(new_item, 2, cancel_btn);
QProgressBar *pgb = new QProgressBar(this);
pgb->setRange(0, new_fl.FileSize/MAX_FILE_PART_SIZE + 1);
pgb->reset();
pgb->setTextVisible(true);
setItemWidget(new_item, 3, pgb);
new_item->setText(4, FileName);
filebuf.clear();
filebuf.write_TLV(TLVS::FILE_NAME, new_item->text(0).toStdString());
filebuf.write_TLV(TLVS::FILE_SIZE, new_fl.FileSize);
filebuf.write_TLV(TLVS::UIN, new_fl.UIN_to);
filebuf.generate_header(HEADER_PACKAGE_TYPE::MESSAGES::SEND_FILE_REQUEST);
new_fl.SeqNumber = filebuf.getPackSeqNumber();
send_to_server(filebuf);
SendingFiles.append(new_fl);
resizeColumnToContents(0);
resizeColumnToContents(1);
resizeColumnToContents(2);
show();
}
void FilesTransferWidget::fileTransferAssignID(Package &pack)
{
// Назначается ID передаваемому файлу.
int i;
HEADER h;
if (!pack.decode_header(h)) return;
// Найдем файл по номеру пакета.
for (i = 0; i < SendingFiles.size(); i++)
if (SendingFiles.value(i).SeqNumber == h.seq)
break;
if (i == SendingFiles.size()) return;
TLV tlv;
if (pack.decode_TLV(TLVS::ERRORS, tlv))
{
emit showTrayMessage(trUtf8("Установка ID файла: ") +
QFileInfo(
QString::fromStdString(
SendingFiles[i].FileName)).fileName(),
QString::fromStdString(tlv.getString()),
QSystemTrayIcon::Critical);
deleteFileRecord(SendingFiles, i, Error,
QString::fromStdString(tlv.getString()), false);
return;
}
if (pack.decode_TLV(TLVS::FILE_ID, tlv))
SendingFiles[i].FileID = tlv.getUIntN<FILE_ID>();
}
void FilesTransferWidget::fileTransferAccepted(Package &pack)
{
// Рассматривается accept на запрос передачи файла.
TLV tlv;
int i;
if (pack.decode_TLV(TLVS::FILE_ID, tlv))
{
FILE_ID fid = tlv.getUIntN<FILE_ID>();
for (i = 0; i < SendingFiles.size(); i++)
if (SendingFiles.value(i).FileID == fid)
break;
if (i == SendingFiles.size())
{
// Отправка файла отменена пользователем, выслать CANCEL.
Package pack2;
pack2.write_TLV(TLVS::FILE_ID, fid);
pack2.write_TLV(TLVS::FILE_CANCEL);
pack2.generate_header(
HEADER_PACKAGE_TYPE::MESSAGES::FILE_SENDER_CHANNEL);
send_to_server(pack2);
return;
}
if (pack.decode_TLV(TLVS::OK, tlv))
{
SendingFiles[i].accepted = true;
SendingFiles[i].finished = false;
SendingFiles[i].canceled = false;
sendNewPartsOfFiles();
}
else
{
if (pack.decode_TLV(TLVS::ERRORS, tlv))
{
emit showTrayMessage(trUtf8("Подтверждение отправка файла: ") +
QFileInfo(QString::fromStdString(
SendingFiles[i].FileName
)
).fileName(),
QString::fromStdString(tlv.getString()),
QSystemTrayIcon::Critical);
deleteFileRecord(SendingFiles, i, Error,
QString::fromStdString(tlv.getString()),
false);
return;
}
else
emit showTrayMessage(trUtf8("Подтверждение отправка файла: ") +
QFileInfo(QString::fromStdString(
SendingFiles[i].FileName
)
).fileName(),
trUtf8("Не обнаружены поля OK|ERR"),
QSystemTrayIcon::Critical);
}
}
else
emit showTrayMessage(trUtf8("Подтверждение отправка файла"),
trUtf8("Не указан ID файла!"),
QSystemTrayIcon::Critical);
}
void FilesTransferWidget::sendNewPartsOfFiles()
{
if (sock->bytesToWrite() > 0) return;
// Отправка порции файла.
if (SendingFiles.isEmpty()) return;
int old_sending_file_number = sending_file_number;
while (!SendingFiles[sending_file_number].accepted ||
SendingFiles[sending_file_number].canceled ||
SendingFiles[sending_file_number].finished)
{
sending_file_number++;
if (sending_file_number >= SendingFiles.size())
sending_file_number = 0;
if (sending_file_number == old_sending_file_number) return;
}
filebuf.clear();
filebuf.write_TLV(TLVS::FILE_ID,
SendingFiles[sending_file_number].FileID);
uint8_t fpart[MAX_FILE_PART_SIZE];
int bytes =
SendingFiles[sending_file_number].fd->read((char*)fpart,
MAX_FILE_PART_SIZE);
if (bytes > 0)
{
filebuf.write_TLV(TLVS::FILE_PART,
SendingFiles[sending_file_number].current_part++);
filebuf.write_TLV(TLVS::FILE_BODY, bytes, fpart);
filebuf.generate_header(HEADER_PACKAGE_TYPE::MESSAGES::SEND_FILE_PART);
if (SendingFiles[sending_file_number].reference != NULL)
{
QTreeWidgetItem* item = (QTreeWidgetItem*)
SendingFiles[sending_file_number].reference;
QProgressBar *pb = (QProgressBar*)itemWidget(item, 3);
pb->setValue(pb->value() + 1);
}
}
else
{
if (bytes < 0)
{
// Файл испорчен или был удален в процессе передачи.
filebuf.write_TLV(TLVS::ERRORS,
string("Исходный файл испорчен или удален!"));
filebuf.generate_header(
HEADER_PACKAGE_TYPE::MESSAGES::FILE_SENDER_CHANNEL);
send_to_server(filebuf);
deleteFileRecord(SendingFiles, sending_file_number, Error,
trUtf8("Исходный файл испорчен или удален!"),
false);
if (sending_file_number >= SendingFiles.size())
sending_file_number = 0;
return;
}
// Передача файла завершена, выслать хэш.
SendingFiles[sending_file_number].fd->close();
SendingFiles[sending_file_number].finished = true;
CryptoPP::Weak1::MD5 hash;
byte hash_buf[2*CryptoPP::Weak1::MD5::DIGESTSIZE];
string str_fname = SendingFiles[sending_file_number].FileName;
#if defined(_OS_WINDOWS_)
QString fname = QString::fromStdString(
SendingFiles[sending_file_number].FileName);
QTextCodec::setCodecForCStrings(
QTextCodec::codecForName("Windows-1251"));
str_fname = fname.toStdString();
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
#endif
CryptoPP::FileSource f(str_fname.c_str(),
true, new CryptoPP::HashFilter(hash,
new CryptoPP::HexEncoder(
new CryptoPP::ArraySink(hash_buf,
2*CryptoPP::Weak1::MD5::DIGESTSIZE))));
filebuf.write_TLV(TLVS::FILE_HASH, 2*CryptoPP::Weak1::MD5::DIGESTSIZE,
hash_buf);
filebuf.generate_header(
HEADER_PACKAGE_TYPE::MESSAGES::FILE_SENDER_CHANNEL);
}
send_to_server(filebuf);
// Переходим к следующему отправляемому файлу.
sending_file_number++;
if (sending_file_number >= SendingFiles.size())
sending_file_number = 0;
}
void FilesTransferWidget::newFilePart(Package &pack)
{
// Запись порции загружаемого файла на диск.
TLV tlv;
FILE_ID fid;
int i;
if (pack.decode_TLV(TLVS::FILE_ID, tlv))
fid = tlv.getUIntN<FILE_ID>();
else return;
for (i = 0; i < ReceivingFiles.size(); i++)
if (ReceivingFiles.value(i).FileID == fid)
break;
if (i == ReceivingFiles.size())
{
// Получение файла отменено пользователем, выслать CANCEL.
Package pack2;
pack2.write_TLV(TLVS::FILE_ID, fid);
pack2.write_TLV(TLVS::FILE_CANCEL);
pack2.generate_header(
HEADER_PACKAGE_TYPE::MESSAGES::FILE_RECEIVER_CHANNEL);
send_to_server(pack2);
return;
}
if (!ReceivingFiles[i].accepted || ReceivingFiles[i].finished ||
ReceivingFiles[i].canceled) return;
FPART_NUMBER new_part;
if (pack.decode_TLV(TLVS::FILE_PART, tlv))
new_part = tlv.getUIntN<FPART_NUMBER>();
else
{
Package pack2;
pack2.write_TLV(TLVS::FILE_ID, fid);
pack2.write_TLV(TLVS::ERRORS,
string("Не указан номер части файла!"));
pack2.generate_header(
HEADER_PACKAGE_TYPE::MESSAGES::FILE_RECEIVER_CHANNEL);
send_to_server(pack2);
emit showTrayMessage(trUtf8("Загрузка файла: ") +
QFileInfo(QString::fromStdString(
ReceivingFiles.value(i).FileName)).fileName(),
trUtf8("Ошибка загрузки"),
QSystemTrayIcon::Critical);
deleteFileRecord(ReceivingFiles, i, Error,
trUtf8("Не указан номер части файла!"), true);
return;
}
if (new_part > ReceivingFiles[i].current_part)
{
// Потерялась часть файла.
Package pack2;
pack2.write_TLV(TLVS::FILE_ID, fid);
pack2.write_TLV(TLVS::ERRORS, string("Потеряна часть файла!"));
pack2.generate_header(
HEADER_PACKAGE_TYPE::MESSAGES::FILE_RECEIVER_CHANNEL);
send_to_server(pack2);
emit showTrayMessage(trUtf8("Загрузка файла: ") +
QFileInfo(QString::fromStdString(
ReceivingFiles.value(i).FileName)).fileName(),
trUtf8("Ошибка загрузки"),
QSystemTrayIcon::Critical);
deleteFileRecord(ReceivingFiles, i, Error,
trUtf8("Потеряна часть файла!"), true);
return;
}
else if (new_part < ReceivingFiles[i].current_part) return;
ReceivingFiles[i].current_part++;
if (pack.decode_TLV(TLVS::FILE_BODY, tlv))
{
FSIZE len = ReceivingFiles[i].fd->write((char*)tlv.V, tlv.L);
ReceivingFiles[i].received_bytes += len;
if (len != tlv.L)
{
Package pack2;
pack2.write_TLV(TLVS::FILE_ID, fid);
pack2.write_TLV(TLVS::ERRORS,
string("Закончилось место на диске!"));
pack2.generate_header(
HEADER_PACKAGE_TYPE::MESSAGES::FILE_RECEIVER_CHANNEL);
send_to_server(pack2);
emit showTrayMessage(trUtf8("Загрузка файла: ") +
QFileInfo(QString::fromStdString(
ReceivingFiles[i].FileName
)
).fileName(),
trUtf8("Закончилось место на диске"),
QSystemTrayIcon::Critical);
deleteFileRecord(ReceivingFiles, i, Error,
trUtf8("Закончилось место на диске!"), true);
return;
}
if (ReceivingFiles[i].reference != NULL)
{
QTreeWidgetItem* item =
(QTreeWidgetItem*) ReceivingFiles[i].reference;
QProgressBar *pb = (QProgressBar*)itemWidget(item, 3);
pb->setValue(pb->value() + 1);
}
}
else
{
Package pack2;
pack2.write_TLV(TLVS::FILE_ID, fid);
pack2.write_TLV(TLVS::ERRORS,
string("Отсутствует тело части файла!"));
pack2.generate_header(
HEADER_PACKAGE_TYPE::MESSAGES::FILE_RECEIVER_CHANNEL);
send_to_server(pack2);
emit showTrayMessage(trUtf8("Загрузка файла: ") +
QFileInfo(QString::fromStdString(
ReceivingFiles[i].FileName
)
).fileName(),
trUtf8("Ошибка загрузки"),
QSystemTrayIcon::Critical);
deleteFileRecord(ReceivingFiles, i, Error,
trUtf8("Отсутствует тело части файла!"), true);
return;
}
}
void FilesTransferWidget::sender_channel(Package &pack)
{
// Высылаемые со стороны отправителя, я - получатель.
TLV tlv;
FILE_ID fid;
int i;
if (pack.decode_TLV(TLVS::FILE_ID, tlv))
fid = tlv.getUIntN<FILE_ID>();
else return;
for (i = 0; i < ReceivingFiles.size(); i++)
if (ReceivingFiles.value(i).FileID == fid)
break;
if (i == ReceivingFiles.size())
{
// Получение файла отменено мной, выслать CANCEL.
Package pack2;
pack2.write_TLV(TLVS::FILE_ID, fid);
pack2.write_TLV(TLVS::FILE_CANCEL);
pack2.generate_header(
HEADER_PACKAGE_TYPE::MESSAGES::FILE_RECEIVER_CHANNEL);
send_to_server(pack2);
return;
}
if (pack.decode_TLV(TLVS::FILE_HASH, tlv))
{
// Пришел хэш файла, значит загрузка завершена, закроем файл
// и посчитаем его хэш чтобы сравнить.
Package pack2;
ReceivingFiles[i].finished = true;
ReceivingFiles[i].fd->flush();
ReceivingFiles[i].fd->close();
if (ReceivingFiles[i].received_bytes != ReceivingFiles[i].FileSize)
{
pack2.write_TLV(TLVS::FILE_ID, fid);
pack2.write_TLV(TLVS::ERRORS,
string("Файл загружен не полностью!"));
pack2.generate_header(
HEADER_PACKAGE_TYPE::MESSAGES::FILE_RECEIVER_CHANNEL);
send_to_server(pack2);
emit showTrayMessage(trUtf8("Загрузка файла: ") +
QFileInfo(QString::fromStdString(
ReceivingFiles[i].FileName
)
).fileName(),
trUtf8("Ошибка загрузки"),
QSystemTrayIcon::Critical);
deleteFileRecord(ReceivingFiles, i, Error,
trUtf8("Файл загружен не полностью!"), true);
return;
}
if (tlv.L != 2*CryptoPP::Weak1::MD5::DIGESTSIZE)
{
pack2.write_TLV(TLVS::FILE_ID, fid);
pack2.write_TLV(TLVS::ERRORS, string("MD5 хэш испорчен!"));
pack2.generate_header(
HEADER_PACKAGE_TYPE::MESSAGES::FILE_RECEIVER_CHANNEL);
send_to_server(pack2);
emit showTrayMessage(trUtf8("Загрузка файла: ") +
QFileInfo(QString::fromStdString(
ReceivingFiles[i].FileName
)
).fileName(),
trUtf8("Невозможно проверить "
"корректность файла"),
QSystemTrayIcon::Warning);
deleteFileRecord(ReceivingFiles, i, Ready,
trUtf8("Невозможно проверить корректность файла!"),
false);
return;
}
CryptoPP::Weak1::MD5 hash;
byte hash_buf[2*CryptoPP::Weak1::MD5::DIGESTSIZE];
string str_fname = ReceivingFiles.value(i).FileName;
#if defined(_OS_WINDOWS_)
QString fname =
QString::fromStdString(ReceivingFiles.value(i).FileName);
QTextCodec::setCodecForCStrings(
QTextCodec::codecForName("Windows-1251"));
str_fname = fname.toStdString();
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
#endif
CryptoPP::FileSource f(str_fname.c_str(),
true, new CryptoPP::HashFilter(hash,
new CryptoPP::HexEncoder(
new CryptoPP::ArraySink(hash_buf,
2*CryptoPP::Weak1::MD5::DIGESTSIZE))));
for (int k = 0; k < 2*CryptoPP::Weak1::MD5::DIGESTSIZE; k++)
if (tlv.V[k] != hash_buf[k])
{
pack2.write_TLV(TLVS::FILE_ID, fid);
pack2.write_TLV(TLVS::ERRORS,
string("MD5 файла не совпадают!"));
pack2.generate_header(
HEADER_PACKAGE_TYPE::MESSAGES::FILE_RECEIVER_CHANNEL);
send_to_server(pack2);
emit showTrayMessage(trUtf8("Загрузка файла: ") +
QFileInfo(QString::fromStdString(
ReceivingFiles[i].FileName
)
).fileName(),
trUtf8("Загруженный файл испорчен"),
QSystemTrayIcon::Critical);
deleteFileRecord(ReceivingFiles, i, Error,
trUtf8("Загруженный файл испорчен!"), true);
return;
}
pack2.write_TLV(TLVS::FILE_ID, fid);
pack2.write_TLV(TLVS::OK);
pack2.generate_header(
HEADER_PACKAGE_TYPE::MESSAGES::FILE_RECEIVER_CHANNEL);
send_to_server(pack2);
emit showTrayMessage(trUtf8("Загрузка файла: ") +
QFileInfo(QString::fromStdString(
ReceivingFiles[i].FileName
)
).fileName(),
trUtf8("Файл загружен :)"),
QSystemTrayIcon::Information);
if (ReceivingFiles.value(i).reference != NULL)
{
QTreeWidgetItem* item =
(QTreeWidgetItem*) ReceivingFiles.value(i).reference;
removeItemWidget(item, 3);
QToolButton *open_btn = new QToolButton(this);
open_btn->setIcon(QIcon(QPixmap(":/file-transfer/file-transfer"
"-open.png")));
open_btn->setToolButtonStyle(Qt::ToolButtonIconOnly);
open_btn->setToolTip(trUtf8("Открыть файл"));
open_btn->setAutoRaise(true);
connect(open_btn, SIGNAL(clicked()), SLOT(slotOpenFile()));
setItemWidget(item, 3, open_btn);
QToolButton* cbtn = (QToolButton*)itemWidget(item, 2);
cbtn->setToolTip(trUtf8("Удалить запись"));
cbtn->setIcon(QIcon(QPixmap(":/file-transfer/row-delete.png")));
}
delete ReceivingFiles.value(i).fd;
ReceivingFiles.removeAt(i);
return;
}
if (pack.decode_TLV(TLVS::FILE_CANCEL, tlv))
{
// Отправитель отменил передачу. Удалим запись о файле и сам файл.
emit showTrayMessage(trUtf8("Загрузка файла: ") +
QFileInfo(QString::fromStdString(
ReceivingFiles[i].FileName
)
).fileName(),
trUtf8("Загрузка файла отменена отправителем"),
QSystemTrayIcon::Critical);
deleteFileRecord(ReceivingFiles, i, Cancel,
trUtf8("Загрузка файла отменена отправителем"), true);
return;
}
if (pack.decode_TLV(TLVS::ERRORS, tlv))
{
// На стороне отправителя произошла ошибка.
// Удалим запись о файле и сам файл.
emit showTrayMessage(trUtf8("Загрузка файла: ") +
QFileInfo(QString::fromStdString(
ReceivingFiles[i].FileName
)
).fileName(),
QString::fromStdString(tlv.getString()),
QSystemTrayIcon::Critical);
deleteFileRecord(ReceivingFiles, i, Error,
QString::fromStdString(tlv.getString()), true);
return;
}
}
Размещено на Allbest.ru
Подобные документы
Создание клиент-серверного приложения "Чат" с помощью среды визуальной разработки приложений Borland C++ Builder версии 6. Описание функциональности приложения: наличие клиент-серверной архитектуры, обмен короткими сообщениями, а также передача файлов.
курсовая работа [302,0 K], добавлен 30.01.2012Изучение истории достижений корпорации Oracle. Разработка клиент-серверного приложения на языке Delphi XE, реализующего возможность управления персоналом на предприятии. Основные структуры данных. Создание инструкции работы с приложением "Отдел кадров".
дипломная работа [974,7 K], добавлен 08.06.2013Сетевое программное обеспечение: общее понятие, содержание, функции. Этапы развития теории компьютерных сетей. Проектирование в среде программирования Borland Builder C++ клиент серверного приложения с использованием сокетов, листинг данной программы.
курсовая работа [191,5 K], добавлен 07.01.2015Многоуровневые архитектуры клиент–сервер. Диаграммы классов, реализующих уровни презентации, бизнес–логики и базы данных приложения. Словесное описание процесса выполнения транзакций. Создание, изменение и удаление хранимых процедур, их выполнение.
курсовая работа [3,4 M], добавлен 23.03.2013Разработка компьютерной сети. Спецификация и расчет себестоимости спроектированной сети. Выбор инструментальных средств для реализации разрабатываемого клиент-серверного приложения. Описание логической структуры программного продукта, основные алгоритмы.
курсовая работа [942,1 K], добавлен 19.03.2012Разработка конфигурации службы. Исследование вычислительной эффективности алгоритма оптимизации. Программная реализация клиент-серверного приложения. Алгоритм решения непрерывной задачи загрузки рюкзака. Подключение веб-сервиса к клиентскому приложению.
курсовая работа [1,4 M], добавлен 21.01.2017Разработка клиент-серверного приложения, позволяющего взаимодействовать друг с другом с использованием доступа к базам данных. Проектирование связи сервера с базой данных с помощью технологии ODBC. Разработка интерфейса программы, ее тестирование.
курсовая работа [352,0 K], добавлен 24.08.2016Основные концепции разработки приложения в трёхуровневой архитектуре. Проектное решение, реализующее модель реляционной БД. Спецификация на разработку интерфейса. Описание выполнения транзакций прибытия и убытия судна. Инсталляционные файлы приложения.
курсовая работа [4,0 M], добавлен 26.12.2011Создание клиент-серверного приложения на основе технологии CORBA. Проектирование многоуровневой системы, в которой клиент при помощи банкомата выполняет необходимые операции. Способы реализации серверов в разных каналах для ускорения обработки данных.
лабораторная работа [1,1 M], добавлен 08.06.2009Характеристика разновидностей программной реализации чатов. Разработка программы клиент-серверного чата с возможность общения в локальной сети нескольких человек одновременно. Протокол взаимодействия клиента и сервера. Порядок работы с программой.
курсовая работа [530,7 K], добавлен 25.04.2015