D
In Qt Version 5.7, an interesting toolkit, such as a transactional reading, appeared. In addition to the declared verification of the integrity of the series of data sent by a series of data interceptors QDataStreamthe mechanism shall also verify the type and size of each of the entries received.Thus, the integrity of data (data series) can be monitored in a simple way:void SocketManager::socketSendMessage(const QVariant &var) {
QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly);
stream.setVersion(QDataStream::Qt_DefaultCompiledVersion);
stream << var;
_socket->write(data);
}
void SocketManager::onSocketReceiveMessage() {
QDataStream stream(_socket);
stream.setVersion(QDataStream::Qt_DefaultCompiledVersion);
while(_socket->bytesAvailable()) {
stream.startTransaction();
QVariant var;
stream >> var;
if(stream.commitTransaction() == false) return;
// Работаем с данными...
}
}
If the data were not fully obtained or were not in line with expectations (in the example, this type QVariantthe transaction will not be completed. In this case, the reaction may vary depending on the author ' s fantasy of the code. You can wait a little while before the bottom-up approach. An unsuccessful compendium could be incredibly incredibly inspired, and it was important to take some steps.If there is no certainty that this is sufficient, an additional mechanism that, although not designed to verify the correctness of the data, may be used. For example, this may be a routine decompression from the archives:QByteArray SocketManager::compressData(const QVariant &var) {
QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly);
stream.setVersion(QDataStream::Qt_DefaultCompiledVersion);
stream << var;
return qCompress(data, 9);
}
QVariant SocketManager::uncompressData(const QByteArray &data) {
QByteArray raw_data = qUncompress(data);
if(raw_data.isEmpty()) return QVariant();
QDataStream stream(raw_data);
stream.setVersion(QDataStream::Qt_DefaultCompiledVersion);
QVariant var;
stream >> var;
return var;
}
Well, of course, there's still a little reflexing the dispatch code and getting it:void SocketManager::socketSendMessage(const QVariant &var) {
QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly);
stream.setVersion(QDataStream::Qt_DefaultCompiledVersion);
stream << compressData(var);
_socket->write(data);
}
void SocketManager::onSocketReceiveMessage() {
QDataStream stream(_socket);
stream.setVersion(QDataStream::Qt_DefaultCompiledVersion);
while(_socket->bytesAvailable()) {
stream.startTransaction();
QByteArray data;
stream >> data;
// Если не докачалось, то ждём новую порцию данных.
if(data.isEmpty() == true) {
// QByteArray подвержен сериализации также,
// как и другие контейнеры со вставкой размера
// перед началом данных, поэтому если по факту
// данных будет меньше, нежели чем было записано,
// то буфер окажется пустой.
stream.rollbackTransaction();
return;
}
// Целостность (соответствие размеру) проверили,
// теперь пытаемся проверить корректность.
QVariant var = uncompressData(data);
// Порядок.
if(var.isValid() == true) {
// Поскольку "commit" в случае неуспеха
// сделает "rollback" и возвратит позицию
// чтения на начало транзакции, то в ситуации
// с необходимостью отбрасывания повреждённых
// данных расположение "commit" до проверки их
// корректности не имеет смысла.
if(stream.commitTransaction() == false) {
// Этот исход вряд ли возможен
// после всех проверок.
}
}
// Возникли проблемы с корректностью данных.
else {
// "abort" вызовет "commit" со сдвигом
// позиции на место, находящееся после
// повреждённых данных.
stream.abortTransaction();
}
// Работаем с данными...
}
}
In addition to the fact that the amount of information transferred may be reduced several times, in case of data damage, the probability that the packaging will be successful decreases.SupplementIf dealing with transactions that do not account for investment (this is also supported), each of them is:startTransaction() Reminds the current reading position in the buffer;commitTransaction() - removes the data in the buffer, with thenull
Reading position;rollbackTransaction() - returns reading, not
Using data;abortTransaction() - actually as well as commitTransaction(), but it'll be fixed. QDataStream::ReadCorruptData♪