Russian Qt Forum
Ноябрь 23, 2024, 17:50 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 [2]   Вниз
  Печать  
Автор Тема: [РЕШЕНО]QTcpSocket не успевает принять пакеты отправленные в теле цикла while.  (Прочитано 12394 раз)
voron1980
Гость
« Ответ #15 : Сентябрь 04, 2012, 15:31 »

Нет идей почему данные иногда искажаются?
Видимо не все считываете. А вообще код выложить не помешало-бы, или он у вас с первого поста не менялся?
Поменялся(файлы прикрепил), пробую даже писать не на диск, временно кидаю в память и при отключении от сокета сразу скидываю на диск.
Вот пример нужно только в переменные wFName и rFName прописать пути файлов которые будут считываться и записываться, wFName1 нужен для проверки, что бы сравнивать каким должен был быть файл и wFName как его перекосило отправкой. После отключения wFName1 стирается на диске.
При передаче по сети 9Мб файл не всегда битый, а вот 78Мб например всегда, и если я кидаю в память то данных теряется меньше, а если писать сразу на диск то из 78Мб теряется ~1Мб если через буфер то теряется примерно ~200Кб.
« Последнее редактирование: Сентябрь 04, 2012, 15:34 от voron1980 » Записан
fuCtor
Гость
« Ответ #16 : Сентябрь 04, 2012, 18:32 »

Посмотрел код, не знаю может так и можно, но учитывая что сокеты используются асинхронные, то в таком же стиле нужно и читать/отправлять данные (так будет надежней), возможно где-то недочитывали данные, либо недосылали.

Переписал в клиенте и сервере эти части, сделал полностью асинхронными. Проверил на файле в 88Мб, после приема сверил контрольные суммы, все сошлось.

Клиент:
Код
C++ (Qt)
void MainWindow::on_pbSendTest1_clicked()
{
 
   QPointer<QFile> sendFile( new QFile(rFName));
 
if(sendFile->open(QFile::ReadOnly))
{
_sok->setProperty("file", QVariant::fromValue(sendFile));
QDataStream out(_sok);
 
out << quint16(0xCFCF);
out << qint64(sendFile->size());
 
_sok->write(sendFile->read(1300));
}
 
}
 
void MainWindow::OnbytesWritten(qint64 bytes)
{
   QTcpSocket * socket_ = qobject_cast<QTcpSocket*>(sender());
if(!socket_)
return;
 
QPointer<QFile> sendFile = socket_->property("file").value< QPointer<QFile> >();
if(sendFile.isNull())
return;
 
if(sendFile->atEnd())
{
sendFile->close();
delete sendFile.data();
_sok->setProperty("file", QVariant());
qDebug("File sended.");
} else {
socket_->write(sendFile->read(bytes));
}
}
 


Сервер:
Код
C++ (Qt)
void MyThread::readyRead()
{
QTcpSocket * socket_ = socket;
 
if(!socket_)
return;
 
QPointer<QFile> receiveFile = socket_->property("file").value< QPointer<QFile> >();
if(receiveFile.isNull())
{
if(socket_->bytesAvailable() >= (sizeof(quint16) + sizeof(qint64)) )
{
QDataStream in(socket_);
quint16 marker_ = 0;
qint64 fileSize_ = 0;
in >> marker_;
in >> fileSize_;
 
if(marker_ == 0xCFCF)
{
receiveFile = new QFile(wFName);
receiveFile->open(QFile::WriteOnly);
 
 
socket_->setProperty("file", QVariant::fromValue(receiveFile));
 
socket_->setProperty("remaining_size", QVariant::fromValue(fileSize_));
 
qDebug() << "Start file receiving. Size = " << fileSize_;
}
} else {
 
return;
}
}
 
 
if(receiveFile)
{
 
qint64 remainingSize = socket_->property("remaining_size").value<qint64>();
while(!socket_->atEnd() && remainingSize > 0)
{
if(remainingSize > socket_->bytesAvailable())
{
remainingSize -= receiveFile->write(socket_->readAll());
qDebug() << "Remaining size = " << remainingSize;
} else {
remainingSize -= receiveFile->write(socket_->read(remainingSize));
qDebug() << "File received.";
receiveFile->close();
delete receiveFile.data();
socket_->setProperty("file", QVariant());
break;
}
}
 
socket_->setProperty("remaining_size", QVariant::fromValue(remainingSize));
}  
}
 

Исправленную версию с комментариями прикладываю.
Записан
voron1980
Гость
« Ответ #17 : Сентябрь 04, 2012, 23:53 »

Спасибо попробую!
-----

Протестировал работает! Думал использовать QDataStream для передачи приемки, в общем завтра на свежую голову попробую разобраться.
Главное есть маркер и можно понять что за пакет если я не ошибаюсь.
P.S.
К стати если кто будет смотреть пример нужно в конфигурации проекта удалить конфигурацию там где пути к среде компилятора и добавить званого, то что предложит IDE  по умолчанию, а затем добавить вариант сборки, иначе проект не запускается, это наверное так всегда если обмениваться проектами, в общем в первой закладке проекта все решается.
« Последнее редактирование: Сентябрь 05, 2012, 01:03 от voron1980 » Записан
voron1980
Гость
« Ответ #18 : Сентябрь 05, 2012, 17:59 »

То что надо, отличная заготовка для обмена данными без лишних наворотов.

Код:
QObject::setProperty()
QObject::property()
Это для меня было в первые, но довольно удобно хранить там данные для открытого сокета, как я понял.

Еще раз спасибо.
Записан
fuCtor
Гость
« Ответ #19 : Сентябрь 06, 2012, 15:51 »

То что надо, отличная заготовка для обмена данными без лишних наворотов.

Код:
QObject::setProperty()
QObject::property()
Это для меня было в первые, но довольно удобно хранить там данные для открытого сокета, как я понял.

Еще раз спасибо.

Да, если объектов (например сокетов) открытых более одного, то как вариант можно хранить связанные указатели в свойствах, что-бы не использовать массивы/таблицы. Единственное, для большей надежности, после создания экземпляра QFile, лучше ему еще присвоить родителем сокет, что-бы при удалении сокета (где-нибудь раньше времени) удалились и все связанные объекты во избежание утечек.
Записан
Страниц: 1 [2]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.101 секунд. Запросов: 21.