Russian Qt Forum

Qt => Работа с сетью => Тема начата: qtest от Май 02, 2013, 12:21



Название: Передача файлов через QTcpSocket без gui
Отправлено: qtest от Май 02, 2013, 12:21
Здравствуйте. Для курсовой очень нужна наиболее простая программа для отправки/принятия небольшого текстового файла (примерно до 20 символов).
Что-то такое (http://www.prog.org.ru/index.php?topic=16260.msg108026#msg108026), но нужен полностью консольный вариант, без gui. В поиске и в гугле, вроде бы, ничего. Странно вообще, что нигде нет самого простого варианта.


Название: Re: Передача файлов через QTcpSocket без gui
Отправлено: Bepec от Май 02, 2013, 17:46
Не ищи ты в гугле не ищи...

Fortune server/client вам в помощь из примеров.


Название: Re: Передача файлов через QTcpSocket без gui
Отправлено: qtest от Май 03, 2013, 18:17
В нем разобрался, но там тоже гуи, попытался переделать в консольный вариант:
Код:
#include <QCoreApplication>
#include <iostream>
#include <qnetwork.h>
#include <QTcpSocket>
#include <QtNetwork>
using namespace std;

QTcpSocket *tcpSocket;
qint16 port;
qint16 blockSize;
QString currentFortune;


void requestNewFortune()
{
    blockSize = 0;
    tcpSocket->abort();
    tcpSocket->connectToHost(QHostAddress::LocalHost,port);;
}

void readFortune()
{

   QDataStream in(tcpSocket);
    in.setVersion(QDataStream::Qt_4_0);

    if (blockSize == 0) {
        if (tcpSocket->bytesAvailable() < (int)sizeof(quint16))
            return;

        in >> blockSize;
    }

    if (tcpSocket->bytesAvailable() < blockSize)
        return;


    QString nextFortune;
    in >> nextFortune;
  /*  if (nextFortune == currentFortune) {
        QTimer::singleShot(0, this, SLOT(requestNewFortune()));
        return;
    }
 */
    currentFortune = nextFortune;
    currentFortune="test";
  //  statusLabel->setText(currentFortune);
  //  getFortuneButton->setEnabled(true);
}




int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);
    currentFortune="Nothing";
    cin>>port;
    tcpSocket = new QTcpSocket();
    requestNewFortune();
    readFortune();
    cout<<currentFortune.toStdString()<<endl;
    return app.exec();
}
Почему-то не работает, судя по тестам - даже не коннектится к серверу(он точно работает, не переписанный из примера), проблема, видимо, в передаче порта. Как это можно исправить?


Название: Re: Передача файлов через QTcpSocket без gui
Отправлено: Bepec от Май 03, 2013, 18:26
Йоптель моптель. Чтож за день сеня такой. Ещё один ничего не понимающий  в сигналах и слотах. Вы не даёте своему слоту принять информацию :D


Название: Re: Передача файлов через QTcpSocket без gui
Отправлено: kuzulis от Май 03, 2013, 18:56
ГыГы


Название: Re: Передача файлов через QTcpSocket без gui
Отправлено: Bepec от Май 03, 2013, 21:14
Уточню, ведь опять посыпятся вопросы. Вы послали пакет за пивом сообщением. Он не успел ещё с дивана встать, вы от него требуете пиво сообщение!

PS асинхронная у нас сеть, асинхронная.


Название: Re: Передача файлов через QTcpSocket без gui
Отправлено: Fregloin от Май 07, 2013, 19:00
можно сделать и синхронной через waitFor...


Название: Re: Передача файлов через QTcpSocket без gui
Отправлено: Bepec от Май 07, 2013, 19:19
Ещё можно через евентлупы. Но увы, увы.


Название: Re: Передача файлов через QTcpSocket без gui
Отправлено: iukash от Май 11, 2013, 12:40
Ну если не нужна кроссплатформенность (думаю для курсовой вряд ли), не проще ли без qt это реализовать? На c++ куча примеров в гугле!


Название: Re: Передача файлов через QTcpSocket без gui
Отправлено: qtest от Май 16, 2013, 03:43
Цитировать
Ну если не нужна кроссплатформенность (думаю для курсовой вряд ли), не проще ли без qt это реализовать? На c++ куча примеров в гугле!
Лучше бы, конечно, в qt, по ЯП проходим именно его, наверняка это будет плюсом. За фортунсервер/клиент большое спасибо, вроде бы получилось переделать в консольный вариант, но:
client.h
Код:
#ifndef CLIENT_H
 #define CLIENT_H

 #include <QtNetwork>
 #include <QTcpSocket>
 #include <QObject>
 class QTcpSocket;
 class Client : public QObject
 {
     Q_OBJECT

 public:
     Client();
     void start();
     QString output;
 private slots:

     void requestNewFortune();
     void readFortune();

 private:

     QTcpSocket *tcpSocket;
     QString currentFortune;
     quint16 blockSize;

 };
#endif // CLIENT_H

client.cpp
Код:
#include <QtNetwork>
#include "client.h"
#include <QTcpSocket>
#include <QObject>







Client::Client()
{
    tcpSocket = new QTcpSocket(this);
    QObject::connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(readFortune()));
}



void Client::start()
{
    Client::requestNewFortune();
}




void Client::requestNewFortune()
{
    blockSize = 0;
    tcpSocket->abort();
    tcpSocket->connectToHost(QHostAddress::LocalHost,54942); //<<
}

void Client::readFortune()
{
    QDataStream in(tcpSocket);
    in.setVersion(QDataStream::Qt_4_0);

    if (blockSize == 0) {
        if (tcpSocket->bytesAvailable() < (int)sizeof(quint16))
            return;

        in >> blockSize;
    }

    if (tcpSocket->bytesAvailable() < blockSize)
        return;

    QString nextFortune;
    in >> nextFortune;




    currentFortune = nextFortune;
    output=currentFortune;
    //qDebug()<<output;
}

main.cpp
Код:
#include <QCoreApplication>
#include <client.h>
#include <iostream>
int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);
    Client client;
    client.start();
    qDebug()<<client.output;
    return app.exec();


}

qDebug()<<output; в клиент.спп нормально выводит то, что нужно, а qDebug()<<client.output; в мейн выводит только """". Почему так и как это исправить?

Есть примеры вроде Fortune server/client для передачи файлов с клиента на сервер?


Название: Re: Передача файлов через QTcpSocket без gui
Отправлено: Bepec от Май 16, 2013, 07:07
Уточню, ведь опять посыпятся вопросы. Вы послали пакет за пивом сообщением. Он не успел ещё с дивана встать, вы от него требуете пиво сообщение!

PS асинхронная у нас сеть, асинхронная.

Утомляют такие темы. Не понимаешь что тебе пишут - попроси, ещё проще напишу. А если не понимаешь и что-то делаешь, это плохо :D


Название: Re: Передача файлов через QTcpSocket без gui
Отправлено: KrupaKarlo от Май 16, 2013, 08:38
можешь скинуть архивом и сервак и клиент. тогда смогу помочь. А так косяки могут быть где угодно.


Название: Re: Передача файлов через QTcpSocket без gui
Отправлено: Bepec от Май 16, 2013, 08:49
ДА в одном месте у него косяк.

ППЦ. Жаль, что новички читать не умеют...


Название: Re: Передача файлов через QTcpSocket без gui
Отправлено: KrupaKarlo от Май 16, 2013, 09:02
Умеют они читать, просто Верес ты ни одного нормального ответа тут не написал. Ты либо форумный троль, либо тебе просто нечего сказать. Даже не знаю что хуже.


Название: Re: Передача файлов через QTcpSocket без gui
Отправлено: Serr500 от Май 16, 2013, 09:31
qDebug()<<output; в клиент.спп нормально выводит то, что нужно, а qDebug()<<client.output; в мейн выводит только """". Почему так и как это исправить?

Вам уже ответили, но Вы, видимо, даже не потрудились понять ответ. Сеть асинхронная. Client::start инициирует процесс, затем классы начинают общаться посредством сигналов. Сигналы начнут обрабатываться только после входа в Event Loop, то есть после вызова QCoreApplication::exec. Следовательно, до его вызова в вашем клиенте не будет полученных данных, даже если они физически были переданы в ваше приложение. Client::readFortune выводит правильные данные именно потому, что этот слот будет вызван сигналом из сокета уже при выполнении Event Loop.

P.S. Почитайте про асинхронные операции.


Название: Re: Передача файлов через QTcpSocket без gui
Отправлено: Bepec от Май 16, 2013, 09:41
Спасибо тебе Serr500  :) Надеюсь хоть тебя они поймут :D


Название: Re: Передача файлов через QTcpSocket без gui
Отправлено: qtest от Май 16, 2013, 17:55
С первой частью вопроса понятно, ничего не выводилось потому что ничего не успело записаться. А что со второй? Есть какой-нибудь способ получить переменную для мейна, в которой гарантированно будет ответ?
Второй вопрос:
Можно ли избавиться от ошибки "undefined reference to `vtable for Client'"? Всегда появляется, если весь код находится в мейне. Не то, чтобы это было очень важно, но раздражает


Название: Re: Передача файлов через QTcpSocket без gui
Отправлено: Bepec от Май 16, 2013, 19:01
Можно, но придётся использовать костыли на мой взгляд.

Почему бы вас не написать класс который будет ответ выводить спокойно?
Почему вы рвётесь запихать всё в main?
Или у вас это какое - то ограничение?



Название: Re: Передача файлов через QTcpSocket без gui
Отправлено: qtest от Май 16, 2013, 23:10
Первый курс, только начали qt, поэтому пока необходимость использовать классы, особенно в таких случаях, скорее чуть раздражает, чем реально помогает. Как мне пока кажется, удобнее использовать более надежные переменные и работать с более последовательным кодом. Видимо еще не дошел до уровня ООП.
Примерно по этой же причине (очень много лишнего) не нравится пока использовать гуи.
Примеров с отправкой файлов с клиента на сервер все-таки нет? В соседнем треде, по идее, нечто похоже, возможно, заливка на определенный файлообменник была бы даже удобнее.


Название: Re: Передача файлов через QTcpSocket без gui
Отправлено: Bepec от Май 17, 2013, 06:52
Кхм. Вы не читаете? Вам Serr500 повторил, что сеть у нас асинхронная. То есть нет никакой гарантии, что ответ придёт сразу же. Поэтому последовательно оно не выполнится.

Но если в методе клиента в котором вы создаёте запрос, прописать что-то типа
Код:
QEventLoop loop;
connect(networkReply, SIGNAL(finished ()), loop, SLOT(exit()));
loop.start()

Тогда программа не выйдёт из слота и будет ожидать завершения запроса.

НО...

Но сигнал слоты Qt построены на цикле событий QApplication. Проще выражаясь пока вы его не запустите, остальные циклы будут вам выдавать одну скарбезную ошибку (могу ошибаться, но вроде так).

Более надёжные переменные и более последовательный код = больше кода, больше знаний, отсутствие гибкости.
Девиз QT — Code Less Create More, что означает "меньше программируй — больше твори". Вы же от этого принципа отказываетесь ;P


Название: Re: Передача файлов через QTcpSocket без gui
Отправлено: Serr500 от Май 17, 2013, 08:06
Как мне пока кажется, удобнее использовать более надежные переменные и работать с более последовательным кодом. Видимо еще не дошел до уровня ООП.
Видимо так. Ну если уж хотите делать неправильно, то смотрите в сторону QAbstractSocket::waitForReadyRead, QAbstractSocket::waitForBytesWritten, QAbstractSocket::waitForConnected. Не будет никакой асинхронности (точнее говоря, эти методы её скроют), сигналов и слотов. А также гибкости. Будет тупой код на уровне Windows 95.

P.S. Есть одна очень мудрая мысль: "Если у тебя нет времени сделать всё правильно, то где ты потом найдёшь время чтобы всё переделать?"