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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Не могу отправить файл по tcpSocket  (Прочитано 5672 раз)
styu
Гость
« : Сентябрь 02, 2014, 21:13 »

Здравствуйте, уважаемые программисты!
Недавно программирую в Qt и у меня возникли сложности с отправкой файла с сервера с помощью TcpSocket клиенту.
Код сервера:
Сервер:
Код C++ (QT)
void server::writeFile()
{
    QTcpSocket* writeFileSocket = (QTcpSocket*)sender();
    QFile file ("/home/00001-150713_a11.txt");   
    file.open(QIODevice::ReadOnly);
    QByteArray buf = file.readAll();
    writeFileSocket->write(buf, buf.size());
   writeFileSocket->flush();
}
В QByteArray файл записывается, а в writeFileSocket не считывается. Не могу понять в чем причина. Помогите, пожалуйста

Клиент:

Код C++ (QT)
void Client::readFile()
{
    QFile file("/home/my.txt");
    file.open(QIODevice::WriteOnly);
    QByteArray arrFile = tcpSocketReadFile->readAll();
    file.write(arrFile);
    file.close();
}

Записан
torwig
Самовар
**
Offline Offline

Сообщений: 134



Просмотр профиля
« Ответ #1 : Сентябрь 02, 2014, 22:10 »

Наверное, кода маловато приведено.
К какому сигналу коннектится writeFile()?
Если правда в QByteArray файл записывается, а в сокет нет, можно проверить, какое значение возвращает writeFileSocket->write(buf, buf.size()); И вроде можно просто написать writeFileSocket->write(buf);
На клиенте readFile() я так понимаю к сигналу readyRead() подцеплен?
Можно обставить qDebug() и смотреть, что там в этих QByteArray, проверять результат операции file.open().
Записан
Bepec
Гость
« Ответ #2 : Сентябрь 02, 2014, 22:51 »

Хватит маяться самодеятельностью. Берём wireshark, ставим порт и видим всё что отправляется - принимается.

Но если уж код оформить в тег не можем кнопкой [  #  ], то проблема в коде программы.
« Последнее редактирование: Сентябрь 03, 2014, 00:02 от Bepec » Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #3 : Сентябрь 03, 2014, 04:23 »

Скорее всего потому, что данные сразу не приходят.
Записан
styu
Гость
« Ответ #4 : Сентябрь 03, 2014, 09:47 »

Это полный код сервера
Код:
#include "server.h"
#include "ui_server.h"

server::server(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::server)
{
    ui->setupUi(this);
    QTextCodec::setCodecForCStrings(QTextCodec::codecForLocale());
    sessionOpened();
    fortunes<< tr("Ready");
    connect(tcpServer, SIGNAL(newConnection()), this, SLOT(write()));
}

server::~server()
{
    delete ui;
}

void server::sessionOpened()
{
    tcpServer = new QTcpServer(this);
    if (!tcpServer->listen(QHostAddress::Any,3333)) {
        QMessageBox::critical(this, tr("Server"),
                              tr("Unable to start the server: %1.")
                              .arg(tcpServer->errorString()));
        close();
        return;
    }

    QString ipAddress;
    QList<QHostAddress> ipAddressesList = QNetworkInterface::allAddresses();
    for (int i = 0; i < ipAddressesList.size(); ++i) {
        if (ipAddressesList.at(i) != QHostAddress::LocalHost &&
            ipAddressesList.at(i).toIPv4Address()) {
            ipAddress = ipAddressesList.at(i).toString();
            break;
        }
    }
    ui->lineEdit->setText(ipAddress);

    if (ipAddress.isEmpty())
            ipAddress = QHostAddress(QHostAddress::LocalHost).toString();
        ui->lineEdit->setText(ipAddress);
        port = tcpServer->serverPort();
        ui->lineEdit_2->setText(QString::number(port));
       
}


void server::write()
{
    QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_4_0);

    out << (quint16)0;
    out << fortunes.at(qrand() % fortunes.size());
    out.device()->seek(0);
    out << (quint16)(block.size() - sizeof(quint16));


    clientConnection = tcpServer->nextPendingConnection();
    connect(clientConnection, SIGNAL(disconnected()),
            clientConnection, SLOT(deleteLater()));
 
    clientConnection->write(block);
    connect(clientConnection, SIGNAL(readyRead()),this, SLOT(read()));
}

void server::read()
{   
    QTcpSocket* dataSender = (QTcpSocket*)sender();
    QDataStream in(dataSender);
    QString str;
    in >> str;
    ui->lineEdit_3->setText(str);
    if (str == "START")
    {
      writeFile();
    }
}


void server::writeFile()
{

    QTcpSocket* writeFileSocket = (QTcpSocket*)sender();
    QFile file ("/home/tatyana/41101-040313.a11");    // 00001-150713_a11.txt");
    file.open(QIODevice::ReadOnly);
    QByteArray buf = file.readAll();
    int iii = buf.size();
    qDebug() << buf.constData();
    writeFileSocket->write(buf, buf.size());
 }
Записан
styu
Гость
« Ответ #5 : Сентябрь 03, 2014, 09:48 »

Это полный код клиента:
Код:
 
#include "client.h"
#include "ui_client.h"

Client::Client(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::Client)
{
    ui->setupUi(this);

    QTextCodec::setCodecForCStrings(QTextCodec::codecForLocale());
    ui->label_2->setText("<font color =\"#ff0000\">Подключение ...</font>");

    ipAddress = "192.168.0.111"; //220;
    port = 3333;

    fortunes<< tr("Start");

    tcpSocket = new QTcpSocket(this);
    tcpSocketWrite = new QTcpSocket(this);

    connect(tcpSocketWrite, SIGNAL(connected()), SLOT(slotConnected()));

    connect(tcpSocket, SIGNAL(readyRead()), SLOT(slotReadyRead()));
    connect(tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)),
            this,SLOT(slotError(QAbstractSocket::SocketError)));
}

Client::~Client()
{
    delete ui;
    tcpSocket->close();
    tcpSocket->disconnectFromHost();

    tcpSocketWrite->close();
    tcpSocketWrite->disconnectFromHost();
}


void Client::slotReadyRead()
{
    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(requestNew()));
        return;
    }

    currentFortune = nextFortune;

        if (currentFortune == "Ready")
        {
            tcpSocketWrite->connectToHost(ipAddress,port);
        }
    tcpSocket->disconnectFromHost();

}


void Client::slotError(QAbstractSocket::SocketError err)
{
    switch (err) {
    case QAbstractSocket::RemoteHostClosedError:
        break;
    case QAbstractSocket::HostNotFoundError:
        QMessageBox::information(this, tr("Client"),
                                 QObject::trUtf8(" Хост не может быть найден."
                                    "Пожалуйста, проверьте имя хоста и номер порта"));
        break;
    case QAbstractSocket::ConnectionRefusedError:
        QMessageBox::information(this, tr("Client"),
                                 QObject::trUtf8("Нет соединения с сервером! "
                                                "Сервер не был запущен. "
                                                "Запустите, пожалуйста, сервер. "));
        break;
    default:
        QMessageBox::information(this, tr("Client"),
                                 QObject::trUtf8("Ошибка: %1.")
                                 .arg(tcpSocket->errorString()));
    }
}

void Client::readFile()
{
    QFile file("/home/tatyana/my.txt");
    file.open(QIODevice::WriteOnly);
    QByteArray arrFile = tcpSocketReadFile->readAll();
    int jjj = arrFile.size();
    file.write(arrFile);
    file.close();
}

void Client::slotConnected()
{
    QDataStream out(tcpSocketWrite);
    out.setVersion(QDataStream::Qt_4_8);
    out << tr("START");
    ui->textEdit->append(QObject::trUtf8("Отправлен сигнал к запуску чтения!"));
    tcpSocketWrite->close();
    tcpSocketWrite->disconnectFromHost();

    tcpSocketReadFile = new QTcpSocket(this);
    tcpSocketReadFile->connectToHost(ipAddress, port);
    connect(tcpSocketReadFile, SIGNAL(readyRead()), this, SLOT(readFile()));
 }


void Client::on_pushButton_3_clicked()
{
    int f ,cod ,IsLoopBack;
    QString ip;
    for( int index = 0; index < QNetworkInterface::allInterfaces().count(); index++)
     {
        QNetworkInterface current = QNetworkInterface::interfaceFromIndex( index + 1);
        f=current.flags();
        cod =f & QNetworkInterface::IsUp; //карта д.б. активна
        IsLoopBack = f & QNetworkInterface::IsLoopBack; //петлевой интерфейс
        if( cod ==QNetworkInterface::IsUp || IsLoopBack != QNetworkInterface::IsLoopBack)
        {
            if( current.isValid() )  // нет сетевого интерфейса
            {
                if (current.flags().testFlag(QNetworkInterface::IsRunning))
                    ui->label_2->setText("<font color=\"#00aa00\">Сеть подключена ...</font>");
                else
                    ui->label_2->setText("<font color =\"#ff0000\">Нет соединения...</font>");
            }
        }
    }
}



void Client::requestNew()
{
    blockSize = 0;
    tcpSocket->abort();
    tcpSocket->connectToHost(ipAddress,port);
}

void Client::on_pushButton_4_clicked()
{
   requestNew();
}
Записан
torwig
Самовар
**
Offline Offline

Сообщений: 134



Просмотр профиля
« Ответ #6 : Сентябрь 03, 2014, 14:41 »

Хм...
Давайте проясним логику приложения.
Итак есть сервер. Есть клиент, там у вас 2 сокета.
При подключении tcpSocket к серверу, сервер напишет в сокет Ready. Клиент, получив это, отправит серверу Start, и отключится.
После этого с клиента сокет tcpSocketWrite подключится и по идее тоже получит Ready, ...дальше я заблудился)
И все же что должен делать код, Вашими словами.
Записан
Bepec
Гость
« Ответ #7 : Сентябрь 03, 2014, 15:07 »

Всё довольно просто. ТС продублировал TCPSocket, запутался в них и в результате у него получается шишь Улыбающийся
Вот тут бяка.

Код:
 void Client::slotConnected(){
// Да мы подключились tcpSocketWrite'ром.
    QDataStream out(tcpSocketWrite);
    out.setVersion(QDataStream::Qt_4_8);
// запишем в массив СТАРТ
    out << tr("START");
// ага и выведем сообщение что всё хорошо
    ui->textEdit->append(QObject::trUtf8("Отправлен сигнал к запуску чтения!"));
// Эй, эй, парни - вы куда? Я ещё ничего не отправил серверу!!!!
    tcpSocketWrite->close();
// АААА... Я закрыт... Я не смог выполнить миссию
    tcpSocketWrite->disconnectFromHost();
// НЕЕЕТ, я не виноват, не бейте!!! Это всё программист!!!!!!
}
Записан
styu
Гость
« Ответ #8 : Сентябрь 03, 2014, 20:28 »

Цитировать
Хм...
Давайте проясним логику приложения.
Итак есть сервер. Есть клиент, там у вас 2 сокета.
При подключении tcpSocket к серверу, сервер напишет в сокет Ready. Клиент, получив это, отправит серверу Start, и отключится.
После этого с клиента сокет tcpSocketWrite подключится и по идее тоже получит Ready, ...дальше я заблудился)
И все же что должен делать код, Вашими словами.
Именно так все и происходит. А хотелось бы, чтобы после того, как клиент отправит серверу Start, и сервер этот Start получил, сервер отправит в ответ в сокет файл, а клиент его получит. А получается, что tcpSocketWrite сокет с клиента не получает файл, а получает, как Вы и сказали Ready
« Последнее редактирование: Сентябрь 03, 2014, 22:10 от styu » Записан
styu
Гость
« Ответ #9 : Сентябрь 03, 2014, 20:48 »

Код:
void Client::slotConnected(){
// Да мы подключились tcpSocketWrite'ром.
    QDataStream out(tcpSocketWrite);
    out.setVersion(QDataStream::Qt_4_8);
// запишем в массив СТАРТ
    out << tr("START");
// ага и выведем сообщение что всё хорошо
    ui->textEdit->append(QObject::trUtf8("Отправлен сигнал к запуску чтения!"));
// Эй, эй, парни - вы куда? Я ещё ничего не отправил серверу!!!!
    tcpSocketWrite->close();
// АААА... Я закрыт... Я не смог выполнить миссию
    tcpSocketWrite->disconnectFromHost();
// НЕЕЕТ, я не виноват, не бейте!!! Это всё программист!!!!!!
}


tcpSocketWrite как раз свою миссию выполнил, Start он отправил и отключился
Записан
Bepec
Гость
« Ответ #10 : Сентябрь 03, 2014, 21:09 »

Помогите нюше найти в этом коде tcpSocketWrite->write(buf)? Улыбающийся
Код:
void Client::slotConnected(){
// Да мы подключились tcpSocketWrite'ром.
    QDataStream out(tcpSocketWrite);
    out.setVersion(QDataStream::Qt_4_8);
// запишем в массив СТАРТ
    out << tr("START");
// ага и выведем сообщение что всё хорошо
    ui->textEdit->append(QObject::trUtf8("Отправлен сигнал к запуску чтения!"));
// Эй, эй, парни - вы куда? Я ещё ничего не отправил серверу!!!!
    tcpSocketWrite->close();
// АААА... Я закрыт... Я не смог выполнить миссию
    tcpSocketWrite->disconnectFromHost();
// НЕЕЕТ, я не виноват, не бейте!!! Это всё программист!!!!!!
}


PS ни к чему не принуждающий совет - начните новый проект клиента, в котором будет только один QTcpSocket и который будет вести диалог с сервером, а не "одна реплика на один сокет".
« Последнее редактирование: Сентябрь 03, 2014, 21:16 от Bepec » Записан
styu
Гость
« Ответ #11 : Сентябрь 03, 2014, 21:25 »

Код:
QDataStream out(tcpSocketWrite);
а это как же?
Цитировать
S ни к чему не принуждающий совет - начните новый проект клиента, в котором будет только один QTcpSocket и который будет вести диалог с сервером, а не "одна реплика на один сокет".

Я как раз собиралась это сделать
Записан
Bepec
Гость
« Ответ #12 : Сентябрь 04, 2014, 08:29 »

Таки да, я ошибался Улыбающийся Извиняюсь. Сказывается малый опыт работы с DataStream.

update:

Тогда ошибка вот тут. writeFile вы вызываете из метода сервера.
writeFileSocket у вас в этом случае = сервер. Но т.к. у вас отсутствует проверка на валидность указателя и вы применяете C преобразование, я удивлён что у вас ничего не вылетает.
Тут вам вместо (QTcpSocket*) надо использовать qobject_cast<QTcpSocket*>() и проверять указатель на 0. (Это не заставит программу работать, она неверна, но зато это даст необходимую вам обработку ошибки и вы увидите где проваливается процесс).
 
К тому же вы немного не понимаете принцип работы асинхронного соединения. Нет никакой гарантии, что в момент writeFile tcpSocketReadFile  уже создан и подсоединился.

Именно поэтому совет остаётся в силе - реализуйте свой протокол с одним QTcpSocket.

Код:
void server::writeFile()
{

    QTcpSocket* writeFileSocket = (QTcpSocket*)sender();
    QFile file ("/home/tatyana/41101-040313.a11");    // 00001-150713_a11.txt");
    file.open(QIODevice::ReadOnly);
    QByteArray buf = file.readAll();
    int iii = buf.size();
    qDebug() << buf.constData();
    writeFileSocket->write(buf, buf.size());
 }
« Последнее редактирование: Сентябрь 04, 2014, 08:38 от Bepec » Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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