Russian Qt Forum

Qt => Работа с сетью => Тема начата: virtual_root от Ноябрь 07, 2010, 15:56



Название: Передача файлов по сети
Отправлено: virtual_root от Ноябрь 07, 2010, 15:56
Доброго времени суток.
Как мне реализовать следующую задачу: есть два компьютера между ними установлена сеть(через wife). Мне нужно с одного компьютера на другой передать файлы, и сохранить на принимаемом компьютере по определенному пути.
Написала следующий код:
void MainWindow::on_pushButton_clicked()
{
    QFile file("matan.jpg");
    QHttp http;
    http.setHost("192.168.1.25");  // ip-адрес принимаемого компьютера
    http.post("F:\matan.jpg",&file);

}

но почему-то ничего не приходит...Что я не так указала? Может что-то ещё нужно добавить?
P.S. диск F:\ доступен по сети, на него я и пытаюсь записать файл matan.jpg


Название: Re: Передача файлов по сети
Отправлено: BRE от Ноябрь 07, 2010, 16:38
IMHO, ты не очень понимаешь, что такое http вообще и реализация QHttp в частности.  ;)

P.S. диск F:\ доступен по сети, на него я и пытаюсь записать файл matan.jpg
Если этот диск доступен, то можно просто сделать:
bool QFile::copy ( const QString & fileName, const QString & newName ) [static]


Название: Re: Передача файлов по сети
Отправлено: merke от Ноябрь 07, 2010, 16:43
OMG, срочно рыться по форуму и читать темы связанные с передачей файлов по сети!!!


Название: Re: Передача файлов по сети
Отправлено: virtual_root от Ноябрь 07, 2010, 16:44
наверное,я не очень понимаю. Я просто думала что передачу файлов можно так было организовать.
Получается я просто могу скопировать файл с удаленного компьютера?
Можете,пожалуйста,привести пример кода.


Название: Re: Передача файлов по сети
Отправлено: merke от Ноябрь 07, 2010, 17:30
Если реализовывать всё это сокетами по протоколу TCP/IP то придется реализовывать целый протокол.

А лучше посмотри в сторону QFtp

И сеть у тебя не по Wife, а по Wifi


Название: Re: Передача файлов по сети
Отправлено: virtual_root от Ноябрь 07, 2010, 17:45
спасибо)) сейчас как раз и смотрела про QFTP. У меня возник маленький вопрос: получается на одном компьютере должен быть установлен FTP-сервер(он у меня установлен на ноутбуке), и тогда я могу с другого компьютера соединиться со своим FTP-сервером? Или он должен быть обязательно доступен из интернета(как в примере QT\examples\ftp client) ?


Название: Re: Передача файлов по сети
Отправлено: virtual_root от Ноябрь 07, 2010, 18:20
написала следующий код:
 QFile file("matan.mov");
    QFtp ftp;
    if (file.open(QIODevice::WriteOnly)){
    ftp.connectToHost("192.168.1.21");
    ftp.login("access","12345");
    ftp.cd("new");
    ftp.get("file.mov",&file);

запускаю программу на том же компьютере где и FTP сервер, с сервером соединяется, даже файл с таким именем появляется в директории с программой,но почему-то он всегда весит 0 байт. В чём проблема? Я что-то забыла указать?


Название: Re: Передача файлов по сети
Отправлено: BRE от Ноябрь 07, 2010, 18:31
Я что-то забыла указать?
Забыла...  :)
Забыла то, что объект класса QFtp выполняет свою работу ассинхронно, т.е. вызов метода get только запускает загрузку файла, сама же загрузка происходит в дальнейшем.
Ты создаешь объект класса QFtp на стеке, и сразу после завершения этого слота этот объект разрушается (соответственно загрузка прерывается не начавшись).
Создавай объект на куче (через new), что бы увеличить время его жизни.



Название: Re: Передача файлов по сети
Отправлено: virtual_root от Ноябрь 07, 2010, 18:57
Я исправила,но всё тоже самое осталось и теперь программа после нажатия по кнопке ещё и сразу закрывается,скопировав как обычно только название файла мне в директорию...я не могу понять почему,помогите,пожалуйста!
P.S. Ребята,спасибо вам большое за терпение и объяснения)) я пока только учусь всему...


Название: Re: Передача файлов по сети
Отправлено: virtual_root от Ноябрь 07, 2010, 18:58
Забыла привести пример кода,того что получилось:

QFile file("matan.pdf");
    QFtp  *ftp;
    ftp = new QFtp(ftp);
    if (file.open(QIODevice::WriteOnly)){
    ftp->connectToHost("192.168.1.21");
    ftp->login("access","12345");
    ftp->cd("new");
    ftp->get("file.pdf",&file);


Название: Re: Передача файлов по сети
Отправлено: BRE от Ноябрь 07, 2010, 19:32
QFile file("matan.pdf");         // Объект file так же разрушиться при выходе из слота
//    ftp = new QFtp(ftp);         // Не нужно указывать в качестве парента ftp
    QFtp *ftp = new QFtp( this );   // либо не указывай ничего (и удаляй объект ftp сама после завершения загрузки),
                     // или укажи в качестве парента объект, который сам его удалит при своем разрушении


Название: Re: Передача файлов по сети
Отправлено: virtual_root от Ноябрь 07, 2010, 19:42
всё заработало правильно!!!))) BRE огромное вам спасибо))) жалко что на форумах конфеткой не угостишь...хотелось отблагодарить за терпение))


Название: Re: Передача файлов по сети
Отправлено: virtual_root от Ноябрь 07, 2010, 19:52
и ещё один маленький вопросик ;) я на форму добавила QProgreesBar, а как мне связать его с закачкой файла,чтобы видны были проценты загрузки??


Название: Re: Передача файлов по сети
Отправлено: BRE от Ноябрь 07, 2010, 19:54
и ещё один маленький вопросик ;) я на форму добавила QProgreesBar, а как мне связать его с закачкой файла,чтобы видны были проценты загрузки??
void QFtp::dataTransferProgress ( qint64 done, qint64 total ) [signal]


Название: Re: Передача файлов по сети
Отправлено: virtual_root от Ноябрь 07, 2010, 20:03
а что это за параметры мне нужно передать? Это я должна проверять сколько изначально файл весит и каждый раз смотреть сколько байт подгружено потом делить на общее количество, умножать на 100% и передавать в progressbar?


Название: Re: Передача файлов по сети
Отправлено: BRE от Ноябрь 07, 2010, 20:08
а что это за параметры мне нужно передать? Это я должна проверять сколько изначально файл весит и каждый раз смотреть сколько байт подгружено потом делить на общее количество, умножать на 100% и передавать в progressbar?
Это сигнал, это он тебе эти параметры сообщает, а ты уже должна указываешь их progressbar'у.


Название: Re: Передача файлов по сети
Отправлено: virtual_root от Ноябрь 07, 2010, 21:01
Я добавила сигнал, связала его со слотом, но у меня теперь приложение почему-то не запускается...и я не знаю,что мне в фун-и слота писать...!
В конструкторе класса MainWindow добавила:
 ui->progressBar->reset();
connect(ftp,SIGNAL (dataTransferProgress()),progress,SLOT (setProgress()));

соответственно в .h:
public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();
     QFtp  *ftp;  // перенесла его сюда
     QProgressBar* progress;

private:
    Ui::MainWindow *ui;

private slots:
    void on_pushButton_clicked();
    void setProgress();


P.S. понимаю,я вас уже замучила...


Название: Re: Передача файлов по сети
Отправлено: virtual_root от Ноябрь 07, 2010, 21:04
убрала строчку соединения сигнала и слота и всё заработало,но progressbar попрежнему не активен..


Название: Re: Передача файлов по сети
Отправлено: BRE от Ноябрь 07, 2010, 21:11
Вначале нужно хорошо разобраться с сигнально-слотовой системой.
Это основы Qt. Без этого ничего толкового сделать не получиться.  ;)
Читай асистент, смотри примеры.


Название: Re: Передача файлов по сети
Отправлено: virtual_root от Ноябрь 07, 2010, 22:21
будем разбираться;)


Название: Re: Передача файлов по сети
Отправлено: virtual_root от Ноябрь 09, 2010, 01:13
У меня возник ещё один вопрос: а как мне с сервера прочитать атрибуты определенного файла?
Например,дату и время последних изменений в файле?


Название: Re: Передача файлов по сети
Отправлено: BRE от Ноябрь 09, 2010, 08:19
а как мне с сервера прочитать атрибуты определенного файла?
Что подразумевается под сервером?
Если сервер ftp, то в QFtp есть:
int QFtp::list ( const QString & dir = QString() )


Название: Re: Передача файлов по сети
Отправлено: virtual_root от Ноябрь 09, 2010, 09:25
Да, по ftp. Спасибо, посмотрю). И ещё вопрос,пожалуйста,ответьте на него по подробней! Я попробовала написать клиент-сервера через QTcpSocket. У меня возникла проблема: как мне получать номера портов и ip-адрес всех,которые есть в сети? В у меня сеть из трех компьютеров,соединенных не кабелем,а через wifi роутер. Как мне получить их IP-адреса и порт по которому я с ними могу обмениваться данными???


Название: Re: Передача файлов по сети
Отправлено: virtual_root от Ноябрь 09, 2010, 10:04
Кажется с портом я разобралась. Там если поставить , то он выбирвет первый не занятый системой порт. Но как мне получить список всех IP адресов в сети???


Название: Re: Передача файлов по сети
Отправлено: virtual_root от Ноябрь 10, 2010, 21:29
Пожалуйста,подскажите,что не так я пишу?! Почему у меня не передаются сообщения серверу?
Я написала программу клиент-сервер(два в одном). С сервером соединяюсь,получаю от него ответ connected!!!, но сообщение которое я отправляю ему(по нажатию кнопки send) не получаю! Хотя он вроде читает его! Что я всё время упускаю???

Вот код: (файл .h)
Код:
#ifndef SERVERCLIENT_H
#define SERVERCLIENT_H

#include <QtGui>
class QTcpServer;
class QTcpSocket;

class Widget :public QWidget{
    Q_OBJECT
    public:
    QPushButton* connection;
    QPushButton* opendir;
    QPushButton* send;
    QLabel* label_port;
    QLabel* label_answer;
    QLineEdit* IP;
    QLineEdit* Port;
    QLineEdit* letter;
    QTcpServer* TcpServer;
    QTcpSocket* TcpSocket;
    quint16 blockSize;
    Widget();
    public slots:
              void connection_clicked();
              void send_clicked();
              void opendir_clicked();
      virtual void slotNewConnection();
              void slotReadAnswer();
              void sendAnswerToClient(QString& str);
   protected:
            void send_letter_to_client();
};




#endif // SERVERCLIENT_H


Файл .cpp:
Код:
#include "server-client.h"
#include <QDebug>
#include <QFileDialog>
#include <QtNetwork>


Widget::Widget(){
    // кнопка соединения
    connection = new QPushButton(QString("connection"),this);
    QObject::connect(connection,SIGNAL(clicked()),SLOT(connection_clicked()));
    // кнопка отпраки данных
    send = new QPushButton(QString("send"),this);
    QObject::connect(send,SIGNAL(clicked()),SLOT(send_clicked()));
    // кнопка выбора файла
    opendir = new QPushButton(QString("open dir"),this);
    QObject::connect(opendir,SIGNAL(clicked()),SLOT(opendir_clicked()));
    // Label port
    label_port = new QLabel(this);
    label_port->setText("Current Port");
    // Label answer
    label_answer = new QLabel(this);
    label_answer->setText(QString::fromLocal8Bit("Ждём ответа..."));
    // IP
    IP = new QLineEdit(this);
    IP->setText("IP");
    // Port
    Port = new QLineEdit(this);
    Port->setText("Port");
    // Letter
    letter = new QLineEdit(this);
    letter->setText("Enter message");
    // размещение виджетов
    QGridLayout *Layout = new QGridLayout;
    Layout->addWidget(IP,0,0);
    Layout->addWidget(Port,1,0);
    Layout->addWidget(letter,2,0);
    Layout->addWidget(label_port,3,0);
    Layout->addWidget(label_answer,4,0);
    Layout->addWidget(connection,0,1);
    Layout->addWidget(send,1,1);
    Layout->addWidget(opendir,2,1);
    setLayout(Layout);
}


void Widget::connection_clicked(){  //настраиваем сервер на слушание каналов
  TcpServer = new QTcpServer(this);
    if (!TcpServer->listen(QHostAddress::Any,1115)) {
        QMessageBox::critical(this, tr("Server"),
                              tr("Unable to start the server: %1.")
                              .arg(TcpServer->errorString()));
        close();
        return;
    }
    label_port->setText(tr("port %1.\n").arg(TcpServer->serverPort()));  // Выводим порт сервера, если сервер прослушивает соединения, в противном случае выведется 0.
    QObject::connect(TcpServer,SIGNAL(newConnection()),SLOT(slotNewConnection())); // устанавливаем соединение с новым клиентом,который подключился
}

void Widget::send_clicked(){
    TcpSocket = new QTcpSocket(this);
    blockSize = 0;
    TcpSocket->connectToHost(IP->text(),1115);
    send_letter_to_client();
    QObject::connect(TcpSocket, SIGNAL(readyRead()), this, SLOT(slotReadAnswer()));  // читаем ответ сервера
   // посылаем клиенту сообщение
}

void Widget::opendir_clicked(){
  QFileDialog d;
  QString dir_name = d.getExistingDirectory();
}

void Widget::slotNewConnection(){  // создание нового соединения с очередным клиентом
  QString answer="Connected!!!";
  TcpSocket = TcpServer->nextPendingConnection();
  QObject::connect(TcpSocket,SIGNAL(disconnected()),TcpSocket,SLOT(deleteLater()));
  // читаем сообщение клиента,если он что-то нам сообщает
  QObject::connect(TcpSocket, SIGNAL(readyRead()),this,SLOT(slotReadAnswer()));
  sendAnswerToClient(answer);  // отсылаем ответ клиенту
}

void Widget::sendAnswerToClient(QString &str){ // отсылаем сообщение очередному клиенту об успешном соединении
    QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_4_0);
    out << (quint16)0;
    out << str;
    out.device()->seek(0);
    out << (quint16)(block.size() - sizeof(quint16));
    TcpSocket->write(block);
}

void Widget::slotReadAnswer(){
    TcpSocket = (QTcpSocket*)sender();
    QString str;
    QDataStream in(TcpSocket);
    in.setVersion(QDataStream::Qt_4_5);
    for (;;) {
        if (!blockSize) {
            if (TcpSocket->bytesAvailable() < sizeof(quint16)) {
                break;
            }
            in >> blockSize;
        }

        if (TcpSocket->bytesAvailable() < blockSize) {
            break;
        }
        in >> str;
        blockSize = 0;

    }
  label_answer->setText(str);
}

void Widget::send_letter_to_client(){
    TcpSocket = new QTcpSocket(this);
    QString str;
    str = letter->text();
    QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_4_0);
    out << (quint16)0;
    out << str;
    out.device()->seek(0);
    out << (quint16)(block.size() - sizeof(quint16));
    TcpSocket->write(block);
}



Название: Re: Передача файлов по сети
Отправлено: virtual_root от Ноябрь 10, 2010, 22:03
АУ!!! Кто-нибудь может мне помочь????


Название: Re: Передача файлов по сети
Отправлено: virtual_root от Ноябрь 10, 2010, 23:41
пока ответят, уже и сам поймешь в чём проблема...хотя всё же не до конца получается...


Название: Re: Передача файлов по сети
Отправлено: virtual_root от Ноябрь 11, 2010, 00:56
У меня так и не получилось решить проблему...((( если кто добрый поможет,буду рада.


Название: Re: Передача файлов по сети
Отправлено: DmP от Ноябрь 11, 2010, 01:17
Так, посмотрим, что видно на первый взгляд:
Цитировать
void Widget::send_clicked(){
    TcpSocket = new QTcpSocket(this);
    ...
    send_letter_to_client();
И:
Цитировать
void Widget::send_letter_to_client(){
    TcpSocket = new QTcpSocket(this);
Возможно, в этом и причина ...


Название: Re: Передача файлов по сети
Отправлено: virtual_root от Ноябрь 11, 2010, 09:34
void Widget::send_letter_to_client(){
    TcpSocket = new QTcpSocket(this);  - удалила.

Я заметила странную вещь. Беру пример из книги Макса Шлее(server) и с помощью моей программы мои сообщения приходят на этот сервер(настраиваю их на один канал), а вот на мою же программу,которая у меня и клиент и сервер одновременно, они не доходят...
Может кто ещё посмотрит что же не так????


Название: Re: Передача файлов по сети
Отправлено: DmP от Ноябрь 11, 2010, 11:12
Так, смотрим дальше:
Код:
for (;;) {
        if (!blockSize) {
            if (TcpSocket->bytesAvailable() < sizeof(quint16)) {
                break;
            }
            in >> blockSize;
        }

        if (TcpSocket->bytesAvailable() < blockSize) {
            break;
        }
        in >> str;
        blockSize = 0;
    }
Получается, чуть что не так, посылаем все подальше, а кто будет ждать прихода сообщения? А если оно вообще частями будет идти?


Название: Re: Передача файлов по сети
Отправлено: virtual_root от Ноябрь 11, 2010, 20:32
Спасибо вам!  Проблема как-то,но разрешилась. Теперь сообщения передаются в обе стороны,но почему-то именно первое сообщение не доходит... последующее приходит. И почему-то они как-то долго идут..я секунд 5-7 жду! Почему такое происходит??

P.S. Смотрела пример QT (network-chat), там всё замечательно) быстро сообщения приходят,не надо не каких портов и IP- адресов указывать. Я пытаюсь на основе его разобраться и написать что-то похожее. Там как я поняла широковещательный канал используется, но пока я до этого не дошла, не совсем понимаю каким именно образом он работает. Буду очень рада,если вы мне поможете,подскажите где я что-то не не так понимаю и почему в моей маленькой программке сообщения передаются странным образом,а иногда и вообще не доходят...(((

Решила  сразу  всю программу выложить.


Название: Re: Передача файлов по сети
Отправлено: DmP от Ноябрь 11, 2010, 22:36
Все таки следует перечитать мое предыдущее сообщение - в коде логическая ошибка на которую я и указал, она не исправлена.
Далее следует почитать документацию, например, как работают в QAbstractSocket ф-ции connectToHost() и write().
Так же, наверное, не следует на каждую отправку сообщения серверу создавать новое соединение.