Qt socket制作一个简单的文件传输系统

Posted 09w09

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Qt socket制作一个简单的文件传输系统相关的知识,希望对你有一定的参考价值。

服务器

用qt designer设计出服务器界面:

上代码:

Server.pro

#-------------------------------------------------
#
# Project created by QtCreator 2017-02-02T09:56:26
#
#-------------------------------------------------

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = Server
TEMPLATE = app


SOURCES += main.cpp\\
        Widget.cpp

HEADERS  += Widget.h

FORMS    += widget.ui

QT += network

Widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTcpServer>
#include <QTcpSocket>
#include <QTimer>
#include <QFile>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

    void sendData();

private slots:
    void on_button1_clicked();

    void on_button2_clicked();

private:
    Ui::Widget *ui;

    QTcpServer *server;
    QTcpSocket *socket;

    QFile file;//文件对象
    QString fileName;//文件名
    qint64 fileSize;//文件大小
    qint64 sendSize;//已经发送文件的大小

    QTimer timer;
};

#endif // WIDGET_H

Widget.cpp

#include "Widget.h"
#include "ui_widget.h"
#include <QFileDialog>
#include <QFileInfo>
#include <qDebug>

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

    server = new QTcpServer(this);
    server->listen(QHostAddress::Any,6666);

    ui->button1->setEnabled(false);
    ui->button2->setEnabled(false);

    connect(server,&QTcpServer::newConnection,[=](){
        socket = server->nextPendingConnection();
        //获取对方IP,端口
        QString ip =  socket->peerAddress().toString();
        quint16 port = socket->peerPort();

        QString str = QString("[%1:%2] 成功连接").arg(ip).arg(port);
        ui->textEdit->append(str);

        ui->button1->setEnabled(true);

    });
}

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

void Widget::on_button1_clicked()
{
    QString path = QFileDialog::getOpenFileName(this,"OPEN","../");
    if(path == NULL){
        ui->textEdit->append("路径读取失败");//qDebug() << "路径读取失败";
        return;
    }

    //初始化发送信息
    fileName.clear();
    fileSize = 0;
    sendSize = 0;
    //获取信息
    QFileInfo info(path);
    fileName = info.fileName();
    fileSize = info.size();
    //打开文件
    file.setFileName(path);
    if(!file.open(QIODevice::ReadOnly)){
       ui->textEdit->append("文件打开失败");
        return;
    }
    ui->textEdit->append(path);
    ui->button1->setEnabled(false);
    ui->button2->setEnabled(true);

    connect(&timer,&QTimer::timeout,[=](){

        timer.stop();
        sendData();
    });

}

void Widget::on_button2_clicked()
{
    QString head = QString("0&%1&%2").arg(fileName).arg(fileSize);
    //QString head = QString::number(fileSize);
    qint64 len = socket->write(head.toUtf8());
    if( len < 0 ){
        ui->textEdit->append("头文件没有发送成功");
        file.close();
        ui->button1->setEnabled(true);
        ui->button2->setEnabled(false);
    }
    timer.start(20);//防止粘包

}

void Widget::sendData()
{
    qint64 len = 0;
    do{
        len = 0;
        char buf[4*1024] = {0};//每次发送数据大小
        len = file.read(buf,sizeof(buf));//读文件
        len = socket->write(buf,len);//发文件
        sendSize += len;
    }while(len > 0);

    if(sendSize != fileSize){
        file.close();
        ui->textEdit->append("文件未发送完全");
        return ;
    }

    ui->textEdit->append("文件发送完毕");
    file.close();
}

main.cpp

#include "Widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.setWindowTitle("服务器");
    w.show();

    return a.exec();
}

客户端

用qt designer设计出客户端界面:

上代码:

Client.pro

#-------------------------------------------------
#
# Project created by QtCreator 2017-02-02T09:39:48
#
#-------------------------------------------------

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = Client
TEMPLATE = app


SOURCES += main.cpp\\
        Widget.cpp

HEADERS  += Widget.h

FORMS    += widget.ui

QT += network

Widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTcpSocket>
#include <QFile>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

private slots:
    void on_buttonSend_clicked();

private:
    Ui::Widget *ui;

    QTcpSocket *socket;

    QFile file;//文件对象
    QString fileName;//文件名
    qint64 fileSize;//文件大小
    qint64 recvSize;//已经收到的文件的大小

    bool isStart;
};

#endif // WIDGET_H

Widget.cpp

#include "Widget.h"
#include "ui_widget.h"
#include <QHostAddress>

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

    socket = new QTcpSocket(this);

    isStart = true;
    connect(socket,&QTcpSocket::readyRead,[=](){

        QByteArray buf = socket->readAll();
        if(isStart){//接收头
            isStart = false;

            fileName = QString(buf).section("&",0,0);
            fileSize = QString(buf).section("&",1,1).toInt();
            recvSize = 0;

            file.setFileName(fileName);
            if(!file.open(QIODevice::WriteOnly)){
                qDebug() << "打开出错";
                return;
            }
        }
        else{//接收文件

           qint64 len = file.write(buf);
           recvSize += len;

           if(recvSize == fileSize){
               file.close();
               qDebug() << "文件接收完成";

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

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

void Widget::on_buttonSend_clicked()
{
    QString ip = ui->editIP->text();
    quint16 port = ui->editIP_2->text().toInt();

    socket->connectToHost(QHostAddress(ip),port);
}

main.cpp

#include "Widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();

    return a.exec();
}

运行出来就是这个样子:

注意:qt网络编程一定要在pro文件中添加QT += network

 

以上是关于Qt socket制作一个简单的文件传输系统的主要内容,如果未能解决你的问题,请参考以下文章

Qt学习 之 Socket通信(世界上最简单的例子了)

ubuntu16.04 socket传输文件

ubuntu16.04 socket传输文件

转Qt Socket简单通信

如何用Qt的Qudpsocket传输图片文件?

Window下UDP(socket)接和收数据案例