Приветствую всех!
Подозреваю, что вопрос один из стандартных, но я не смог найти ответ.
Если клиенты и сервер. Клиенты передают файлы через QTcpSocket. Взял образец от
Александра (кстати, большое ему спасибо!) - вот этот:
http://www.prog.org.ru/index.php?topic=16260.msg108026#msg108026Всё, в общем-то прекрасно работает.
Возникла же следующая задача: чтобы от каждого клиента файлы принимались в отдельном потоке. За образец взял экзампловский классический threaded fortune server, к которому прикрутил вышеупомянутый код от
Александра. В итоге получилось следующее:
Клиентская часть (так как проблем с ней нет, всё пишется правильно, то только минимально необходимый кусок):
void QLANF::onConnected()
{
QByteArray block;
QDataStream stream(&block, QIODevice::WriteOnly);
stream.setVersion(QDataStream::Qt_4_5);
QFile file(outPath);
file.open(QIODevice::ReadOnly);
QByteArray buf = file.readAll();
stream << quint64(file.size());
stream << CRC32(outPath);
stream << buf;
//qDebug () << "block.size: " << block.size();
fSocket->write(block);
fSocket->flush();
}
Серверная часть (а тут сложности). Код был минимально изменён по сравнению с экзамплом.
fortuneserver.h#ifndef FORTUNESERVER_H
#define FORTUNESERVER_H
#include <QStringList>
#include <QTcpServer>
//! [0]
class FortuneServer : public QTcpServer
{
Q_OBJECT
public:
FortuneServer(QObject *parent = 0);
protected:
void incomingConnection(int socketDescriptor);
private:
QStringList fortunes;
};
//! [0]
#endif
fortuneserver.cpp#include "fortuneserver.h"
#include "fortunethread.h"
#include <stdlib.h>
//! [0]
FortuneServer::FortuneServer(QObject *parent)
: QTcpServer(parent), addrreess("C://Qt/outFirst.txt")
{
/* объявление fortune - ненужное из экзампла*/
}
//! [0]
//! [1]
void FortuneServer::incomingConnection(int socketDescriptor)
{
QString fortune = fortunes.at(qrand() % fortunes.size());
FortuneThread *thread = new FortuneThread(socketDescriptor, fortune, this);
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();
}
//! [1]
fortunethread.h#ifndef FORTUNETHREAD_H
#define FORTUNETHREAD_H
#include <QThread>
#include <QTcpSocket>
//! [0]
class FortuneThread : public QThread
{
Q_OBJECT
public:
FortuneThread(int socketDescriptor, const QString &fortune, QObject *parent);
void run();
signals:
void error(QTcpSocket::SocketError socketError);
private:
int socketDescriptor;
QString text;
QString inPath;
quint64 nextBlockSize;
};
//! [0]
#endif
fortunethread.cpp#include "fortunethread.h"
#include <QtNetwork>
//! [0]
FortuneThread::FortuneThread(int socketDescriptor, const QString &fortune, QObject *parent)
: QThread(parent), socketDescriptor(socketDescriptor), text(fortune),inPath("C://Qt/outFirst.txt")
{
nextBlockSize = 0;
}
//! [0]
//! [1]
void FortuneThread::run()
{
QTcpSocket tcpSocket;// = static_cast<QTcpSocket*>(sender());
connect(&tcpSocket, SIGNAL(readyRead()), this, SLOT(run()));
//! [1] //! [2]
if (!tcpSocket.setSocketDescriptor(socketDescriptor)) {
emit error(tcpSocket.error());
return;
}
//! [2] //! [3]
// qDebug () << "In Thread avail: " << tcpSocket.bytesAvailable();
tcpSocket.waitForReadyRead();
// qDebug () << "In Thread avail2: " << tcpSocket.bytesAvailable();
//nextBlockSize = 0;
forever
{
//qDebug () << "In Thread avail3: " << tcpSocket.bytesAvailable();
QDataStream stream(&tcpSocket);
stream.setVersion(QDataStream::Qt_4_5);
if (nextBlockSize == 0)
{
if (tcpSocket.bytesAvailable() < sizeof(quint64)) {
return;
}
stream >> nextBlockSize;
}
qDebug () << "nextBlockSize: " << nextBlockSize;
if (nextBlockSize >tcpSocket.bytesAvailable()) {
return;
}
quint32 ttt;
stream >> ttt;
QByteArray arrFile;
stream >> arrFile;
//qDebug () << "arrFile.size: " << arrFile.size();
QFile file(inPath);
file.open(QIODevice::WriteOnly);
file.write(arrFile);
qDebug () << "file.size: " << file.size();
nextBlockSize = 0;
}
qDebug () << "discon";
tcpSocket.disconnectFromHost();
tcpSocket.waitForDisconnected();
}
//! [4]
Собственно, в чём проблема: в случае с потоками файлы крупнее пары килобайт не передаются. Как выяснилось qDebug'ами - не считываются на сервере. Выдаётся, что tcpSocket.bytesAvailable() значительно меньше nextBlockSize.
Проходит одна итерация цикла forever, тогда как в беспоточном случае их столько, сколько нужно, чтобы tcpSocket.bytesAvailable() стало больше nextBlockSize.
Возникло подозрение, что если в первом случае я связываю сигнал readyRead:
connect (pSocket, SIGNAL(readyRead()), this, SLOT(pSocketReadyRead()));
то с потоками - нет. Но как связать сигналы правильно - я не понял.
В общем, большая просьба помочь. Кажется, что ошибка не такая уж и большая, но портит всё дело.
Заранее спасибо :-)
P.S. Вышло сумбурно - извините. Если что-то непонятно - постараюсь разъяснить лучше.
P.P.S. Поиском пользовался - не помогло