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

Войти
 
  Начало Форум WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  
  Просмотр сообщений
Страниц: [1] 2 3 4
1  Qt / Работа с сетью / Re: Оцените код передачи файла через QTcpSocket : Июнь 20, 2020, 18:18
если у вас и клиент и сервер в одном проекте
Здравствуйте.
Да, клиент и сервер в одном проекте, т.к. цель данного проекта/кода - написание и проверка корректной передачи файла и данных.
Дальше вы уже сами разносите методы и классы куда вам надо. А это только пример передачи файлов.
Я же для тестов делаю так:
собираю 2 бинарника и разношу по серверам
1) сборка сервера: в main.cpp оставляете только код для создания сервера, клиент комментируете.
Код:
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    MyTcpServer *server = new MyTcpServer;
    QThread *threadServer = new QThread;
    QObject::connect(threadServer, &QThread::started, server, &MyTcpServer::startServer);
    QObject::connect(threadServer, &QThread::finished, server, &MyTcpServer::deleteLater);
    server->moveToThread(threadServer);
    threadServer->start();

    //QThread::msleep(100);

    //TcpClient *client = new TcpClient("127.0.0.1", 1111);
    //QThread *threadClient = new QThread;
    //QObject::connect(threadClient, &QThread::started, client, &TcpClient::startClient);
    //QObject::connect(threadClient, &QThread::finished, client, &TcpClient::deleteLater);
    //client->moveToThread(threadClient);
    //threadClient->start();

    return a.exec();
}

2) Для клиента наоборот.

Или просто создайте два проекта и собирайте каждый отдельно.

https://wiki.qt.io/WIP-How_to_create_a_simple_chat_application - вот тут гляньте пример с транзакциями.
https://stackoverflow.com/a/39149727/7306569 - и тут интересный вариант с транзакциями.
2  Qt / Работа с сетью / Re: Оцените код передачи файла через QTcpSocket : Май 29, 2020, 19:27
2) У твоей синхронной функции почему-то закомментирован waitForBytesWritten, это как раз для блокирующей отправки должно быть.
Закоментил, потому что и так отправляет хорошо. Как говорят, если всё работает хорошо - ничего не трогай.

3) Почему параметрически не передается имя файла и адрес сервера?
Черновой вариант.

4) Повторный вызов метода отправки надо блокировать (кидать ошибку)
Не понял. Где именно кидать ошибку и зачем.

6) Не все переменные инициализированы в конструкторе, это приведет к крэшам
Если посмотреть main.cpp, то можно заметить, что я каждый экземпляр ввожу в отдельный поток.
А если указатель класса инициализировать в конструкторе, то объект создастся не в новом потоке, а в основном (из main.cpp)

Я бы переиспользовал одно TCP соединение
Так в клиенте и сервере везде создаётся по одному сокету и в него пишется через QDataStream.

отправлять файл пакетами, реализовать очередь пакетов на отправку, дополнить отправляемые пакеты размером, чтобы можно было отделить данные одного пакета от другого
Можете показать пример, не совсем понимаю как это пакетами.
Пакеты шлёт уже сам TCP/IP. Это уже другой уровень. Или вы про что то другое?
3  Qt / Работа с сетью / Re: Оцените код передачи файла через QTcpSocket : Май 29, 2020, 18:53
Ну сам код конечно ужасно спроектирован
Спасибо, можете добавить пару замечаний по поводу того, что именно не так.
4  Qt / Работа с сетью / Re: Оцените код передачи файла через QTcpSocket : Май 25, 2020, 19:23
рабочий пример (проект на gihub) былобы удобнее оценивать
Добавил на https://github.com/vebmaster/QtFileTransferViaSocket
5  Qt / Работа с сетью / Оцените код передачи файла через QTcpSocket : Май 17, 2020, 22:10
Здравствуйте.
Потребовалось сделать передачу файла через QTcpSocket. Нагуглил много разных вариантов, которые меня запутали.
Первым способом сделал через передачу длины блока и затем сам блок. Но потом нашёл более продвинутый способ через транзакции, который появился в Qt 5.7. На нём и сделал, асинхронно.
Оцените пожалуйста, правильно ли и на сколько грамотно сделано? Если есть какие то замечания, буду рад узнать их. Спасибо.

Передаю в несколько переменных:
- тип сетевого пакета (файл, сообщение или другое)
Если файл, то:
- имя файла
- размер файла в байтах
- блок данных
- и в конце текстовое сообщение

Код передачи файла:
Код:
enum PacketType
{
    TYPE_NONE = 0,
    TYPE_MSG = 1,
    TYPE_FILE = 2,
};

void TcpClient::socketSendMessage()
{
    QDataStream stream(m_pTcpSocket);
    stream.setVersion(QDataStream::Qt_DefaultCompiledVersion);

    stream << PacketType::TYPE_FILE;

    QString fileName("/mnt/d/1.png");
    QFile file(fileName);
    QFileInfo fileInfo(file);
    qint64 fileSize = fileInfo.size();

    stream << fileName;
    stream << fileSize;

    int countSend = 0;

    if (file.open(QFile::ReadOnly))
    {
        while(!file.atEnd())
        {
            QByteArray data = file.read(32768*8);
            stream << data;
            countSend++;
        }
        qDebug() << Tools::getTime() << "_CLIENT: ------------------------ countSend FINAL: " << countSend;
    }

    file.close();

    qDebug() << Tools::getTime() << "_CLIENT: send file ok";

    QString testStr("TEST_MESSAGE");
    stream << testStr;
}

Код получения файла:
Заголовочный сервера:
Код:
#ifndef MYTCPSERVER_H
#define MYTCPSERVER_H

#include <QObject>
#include <QTcpServer>
#include <QTcpSocket>
#include "global.h"
#include <QFile>


class MyTcpServer : public QObject
{
    Q_OBJECT

public:
    explicit MyTcpServer(QObject *parent = nullptr);
    ~MyTcpServer();

    int number;
    QString str;

public slots:
    void slotNewConnection();
    void slotServerRead();
    void slotClientDisconnected();
    void onSocketReceiveMessage();
    void startServer();

private:
    QTcpServer * mTcpServer;
    QTcpSocket * mTcpSocket;
    qint64 sizeReceivedData;
    QString fileCopy;
    PacketType packetType;

    QString filePath;
    qint64 fileSize;
    QString testStr;
    QByteArray tmpBlock;
    int countSend;

    bool receiveFile(QDataStream &stream);
};

#endif // MYTCPSERVER_H
В конструкторе:
Код:
    packetType = PacketType::TYPE_NONE;
    filePath.clear();
    fileSize = 0;
    testStr.clear();
    sizeReceivedData = 0;
    tmpBlock.clear();
    countSend = 0;
Слот получения сообщения:
Код:
void MyTcpServer::onSocketReceiveMessage()
{
if (!mTcpSocket || !mTcpSocket->bytesAvailable())
return;

qDebug() << Tools::getTime() << "SERVER: --------------------new-----------------------";
qDebug() << Tools::getTime() << "SERVER: onSocketReceiveMessage: bytesAvailable" << mTcpSocket->bytesAvailable();

QDataStream stream(mTcpSocket);
stream.setVersion(QDataStream::Qt_DefaultCompiledVersion);

// Считывание PacketType
if (packetType == PacketType::TYPE_NONE) {
stream.startTransaction();
stream >> packetType;
if (!stream.commitTransaction()) {
qDebug() << Tools::getTime() << "SERVER: packetType - FAIL commitTransaction";
return;
}
qDebug() << Tools::getTime() << "SERVER: type:" << packetType;
}

if (packetType == PacketType::TYPE_MSG)
{
//
}
else if (packetType == PacketType::TYPE_FILE)
{
//====================================================
// Получение filePath

if (filePath.isEmpty()) {
stream.startTransaction();
stream >> filePath;
if (!stream.commitTransaction()) {
qDebug() << Tools::getTime() << "SERVER: filePath - FAIL commitTransaction";
return;
}
qDebug() << Tools::getTime() << "SERVER filePath:" << filePath;
}

//====================================================
// Получение fileSize

if (!fileSize) {
stream.startTransaction();
stream >> fileSize;
if (!stream.commitTransaction()) {
qDebug() << Tools::getTime() << "SERVER: fileSize - FAIL commitTransaction";
return;
}
qDebug() << Tools::getTime() << "SERVER: fileSize:" << fileSize;
}

//====================================================
// Получение файла

if (sizeReceivedData != fileSize)
{
filePath = this->fileCopy; // временная замена имени файла
QFile file(filePath);
file.open(QFile::Append);

// Работа с файлом в цикле "пока в сокете есть данные"
while (!mTcpSocket->atEnd())
{
//====================================================
// Получение tmpBlock

stream.startTransaction();
stream >> tmpBlock;

if (!stream.commitTransaction()) {
qDebug() << Tools::getTime() << "SERVER: tmpBlock - FAIL commitTransaction";
break;
}

qint64 toFile = file.write(tmpBlock);

sizeReceivedData += toFile;
countSend++;

tmpBlock.clear();

if (sizeReceivedData == fileSize)
break;

} // while (!mTcpSocket->atEnd())

file.close();

} // if (sizeReceivedData != fileSize)

if (sizeReceivedData != fileSize)
return;

qDebug() << Tools::getTime() << "SERVER: sizeReceivedData END: " << sizeReceivedData;
qDebug() << Tools::getTime() << "SERVER fileSize ORIG:" << fileSize;
qDebug() << "SERVER: countSend FINAL: " << countSend;


//====================================================
// Получение testStr

if (testStr.isEmpty()) {
stream.startTransaction();
stream >> testStr;
if (!stream.commitTransaction()) {
qDebug() << Tools::getTime() << "SERVER: testStr - FAIL commitTransaction";
return;
}
qDebug() << Tools::getTime() << "SERVER: testStr:" << testStr;
}

qDebug() << Tools::getTime() << "SERVER: END - bytesAvailable:" << mTcpSocket->bytesAvailable();

// Очистка переменных
filePath.clear();
fileSize = 0;
tmpBlock.clear();
sizeReceivedData = 0;
testStr.clear();
countSend = 0;

} // else if (packetType == PacketType::TYPE_FILE)
}
6  Qt / Работа с сетью / Re: Передача массива через QTcpSocket : Май 17, 2020, 09:34
Таким образом мы хотим убедиться что мы обязательно запишем _беззнаковое_ целое размером 8 бит
Так если записали 1 char, а после него QString, то и считывать мы будем так же, 1 char, а после него уже QString. Правильно?
Если так, тогда опять непонято зачем нужен этот S
7  Qt / Работа с сетью / Re: Передача массива через QTcpSocket : Май 13, 2020, 20:09
Код:
out << quint16(0) << quint8('S') << str;
А зачем добавляют quint8('S')? Что это даёт?
8  Qt / Вопросы новичков / Re: symbol _ZdlPvm version Qt_5 not defined in file with link time reference : Апрель 02, 2020, 16:24
symbol _ZdlPvm version Qt_5 not defined
Решение:
в .pro файл проекта добавить:
Код:
CONFIG += c++11
9  Qt / Многопоточное программирование, процессы / Re: Много-поточная работа с сетью : Март 12, 2018, 17:43
По поводу setAutoDelete, у меня такое понятие.

    Bot *bot = new Bot(this, checkBot);
    bot->setAutoDelete(true); // true - поток уничтожается сразу же после завершения работы Bot
    threadPool_bot->start(bot);
10  Qt / Многопоточное программирование, процессы / Re: QRunnable. Сигнал доходит после завершения потока. : Февраль 20, 2017, 20:16
а возможно ли как то управлять колличеством потоков в QThread , как с пулом threadPool->setMaxThreadCount(50)?
11  Qt / Многопоточное программирование, процессы / Re: QRunnable. Сигнал доходит после завершения потокk : Февраль 20, 2017, 20:14
разобрался, спасибо, у куРуннабле отсутствует цикл обработки событий и сигналы во вне он отправлять не может.
подробнее здесь и здесь
12  Qt / Многопоточное программирование, процессы / Re: QRunnable. Сигнал доходит после завершения потока. : Февраль 14, 2017, 19:41
waitForDone убери
тоже самое

Некому ловить сигнал, пул просто вызывает QRunnable::run (а не ждет в цикле событий нитки)
т.е. задействовать сигналы не получится чтоль?
13  Qt / Многопоточное программирование, процессы / Re: QRunnable. Сигнал доходит после завершения потока. : Февраль 13, 2017, 22:24
вот я добавил допустим 10 заданий в пул (пул на 50 потоков)
Код:
threadPool->start(worker);
в worker выполняется работа, которая может занимать разное время, и отправляется сигнал в родительский объект. И у меня получается так, что все 10 сигналов дойдут до слота после завершения всех 10 заданий в одну и туже секунду, а не когда он был отправлен.
Т.е. если первый поток справился за 1 секунду и отправил сигнал, а 10й поток завершился за 30 секунд, то сигнал от 1-го потока всё равно прийдёт когда завершится 10й. (прийдут все 10 сигналов за раз)
14  Qt / Многопоточное программирование, процессы / QRunnable. Сигнал доходит после завершения потока. : Февраль 10, 2017, 19:44
Приветствую.
имеется пул
Код:
    threadPool = new QThreadPool;
    threadPool->setMaxThreadCount(50); // кол-во ПОТОКОВ
    threadPool->setExpiryTimeout(100);
помещаю объект в пул
Код:
    Work *worker = new Work();
    worker->setAutoDelete(true); // true - поток уничтожается сразу же после завершения работы Work
    connect(worker, SIGNAL(goodSignal()), this, SLOT(mySlot()));
    threadPool->start(worker);

после доабавления заданий в очередь пула жду завершения
Код:
threadPool->waitForDone(-1);
но сигналы доходят после завершения потоков. Почему так?
15  Qt / Qt Quick / Re: Что выбрать для десктопа? : Февраль 10, 2017, 19:09
По этому мне даже не понятно, как люди создают программы с использованием QML.
без графического редактора  Улыбающийся
Страниц: [1] 2 3 4

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