It is possible that this solution will do:
void client::sendDatagrams() { QFile file("test.dat"); if(file.open(QFile::ReadOnly)) { // Размер прочитанных из файла данных // и текущее смещение от начала файла. qint64 raw_size = 0, raw_offset = 0; // Константный размер датаграммы. const qint64 datagram_size = 512; // Буфер для временного хранения данных. char raw_data[datagram_size]; // Файл читаем последовательно и ровно столько байт за итерацию, // сколько может быть размещено в буфере. while((raw_size = file.readData(raw_data, datagram_size)) > 0) { // Метод fromRawData() не производит копирование данных. QByteArray data = QByteArray::fromRawData(raw_data, raw_size); // Вычисление хэш-суммы. QByteArray hash = QCryptographicHash::hash(data , QCryptographicHash::Md5).toHex(); // Итоговая датаграмма. QByteArray datagram; // Заполнять её лучше через QDataStream, // поскольку на приёмной стороне будет проще // произвести обратные действия, // чтобы восстановить исходные данные. // Смещение (raw_offset) сохраняем для того, // чтобы на приёмной стороне иметь возможность // воспроизвести порядок следования датаграмм, // т.к. при использовании UDP, последние могут // приходить без соблюдения очерёдности. QDataStream stream(&datagram, QIODevice::WriteOnly); stream << raw_offset; stream << hash; stream << data; Client_Socket->writeDatagram(datagram , QHostAddress::LocalHost, 1234); // Обновление смещения. raw_offset += raw_size; } } }
Added by
The implementation of the receiver may differ from the code in the listing below, depending on the specific task. But suppose you just need to save the resulting file contents.
Of course, before we can write data to a file, it needs to be prepared. For this, the size of the file must be received from the sender before sending the contents of the file. In the source above, this preparatory moment is not considered, since its implementation is virtually no different from transferring the contents of the file, and depends on the preferences of the author of the code.
Suppose that we have already received the size of the file being sent to the receiver, or we know it in advance. Then we create a clean file and change its size exactly as required:
// Файл будет заполнен нулями. QFile file("test-out.dat"); file.resize(file_size);
Then you can take content:
void receiver::readPendingDatagrams() { while(socket->hasPendingDatagrams()) { QByteArray datagram; datagram.resize(socket->pendingDatagramSize()); socket->readDatagram(datagram.data(), datagram.size()); // При считывании данных из потока важно соблюдать // их очерёдность и тип. // Можно не опасаться того, что hash и data // имеют одинаковый тип, т.к. QDataStream // корректно обработает данную ситуацию. QDataStream stream(datagram); qint64 offset = 0; stream >> offset; QByteArray hash; stream >> hash; QByteArray data; stream >> data; // Проверяем хэш-сумму. if(QCryptographicHash::hash(data , QCryptographicHash::Md5).toHex() != hash) { // В случае несовпадения реагируем, // исходя из требований задачи. continue; } // Сохраняем данные, учитывая смещение. if(file.open(QFile::WriteOnly)) { QDataStream stream(&file, QIODevice::WriteOnly); if(stream.skipRawData(offset) == offset) { stream << data; } file.close(); } } }
Added by
If you are not sure that the control datagram containing the file size is safe and sound, then, alternatively, this data can be sent via TCP / IP. It will turn out a mechanism similar in some way to torrents.
Sending datagrams larger than 512 bytes is in general disadvised, as even if they are sent successfully, they are likely to be fragmented by the IP layer before arriving at their final destination.Those. sending larger datagrams is not explicitly prohibited, it only warns that they will be fragmented. - aleks.andr