【UI开发】QT学习(网络编程实现网络调试与文件互传)

(一)背景介绍

昨天学习了基于QT的网络编程,与LINUX下的网络编程十分相似。学完基础知识就决定要自己编写一个类似于NetAssist的网络上位机,并实现其大部分的功能。
当然计算机网络不可能就这么简单只是socket编程,并没有掌握问题的本质,对于计算机网络等以后有时间还得要单独学习一下。
对于我们做嵌入式的人来说,调试一般都会用别人提供好的调试软件。但是可以自己写一个上位机 真的是一件令人兴奋的事情。先看源码。

服务器端:

#ifndef SEVERWIDGET_H
#define SEVERWIDGET_H

#include <QWidget>
#include <QTcpServer>//监听套接字
#include <QTcpSocket>//通信套接字
#include "clintwidget.h"
#include <QFile>
#include <QTimer>
namespace Ui {
class severWidget;
}

class severWidget : public QWidget
{
    Q_OBJECT

public:
    explicit severWidget(QWidget *parent = 0);
    ~severWidget();
    void subprocess();
    void senddata();
    QString getIP() ;
private slots:
    void on_buttonsend_clicked();

    void on_pushButton_2_clicked();

    void on_change_clicked();

    void on_buttonfile_clicked();

    void on_buttonsend_2_clicked();

private:
    Ui::severWidget *ui;
    clintwidget w;
    QTcpServer *tcpsever;
    QTcpSocket *tcpsocket;
    static int severstate;//反映服务器端所处状态
    QFile file;
    QString filename;
    qint64 filesize;
    qint64 sendsize;//已发大小
    QTimer timer;

};

#endif // SEVERWIDGET_H

#include "severwidget.h"
#include "ui_severwidget.h"
#include "clintwidget.h"
#include <QFile>
#include <QFileDialog>
#include <QDebug>
#include <QFileInfo>
#include <QTimer>
#include <QtNetwork>

severWidget::severWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::severWidget)
{
    ui->setupUi(this);
    setWindowTitle("服务器 端口:8888");
    //指针悬空防止没有连接而死机
    tcpsever=NULL;
    tcpsocket=NULL;
    ui->buttonfile->setEnabled(false);
    ui->buttonsend->setEnabled(false);
    ui->buttonsend_2->setEnabled(false);

    //指定父对象可以自动回收空间
    tcpsever=new QTcpServer(this);
    //监听套接字
    tcpsever->listen(QHostAddress::Any,8888);
    //如果成功连接
    connect(tcpsever,&QTcpServer::newConnection,
            [=]()
            {
              //取出套接字
              tcpsocket=tcpsever->nextPendingConnection();
              //获取对方IP端口
              QString ip=tcpsocket->peerAddress().toString();
              quint16 port =tcpsocket->peerPort();
              QString temp=QString("[%1:%2]:成功连接").arg(ip).arg(port);
              qDebug()<<getIP();
              ui->buttonfile->setEnabled(true);
              ui->buttonsend->setEnabled(true);
//              ui->buttonsend_2->setEnabled(true);


              ui->textEditRead->setText(temp);
              connect(tcpsocket,&QTcpSocket::readyRead,
              [=]()
              {
                  //从通信套接字中取出内容
                  QByteArray array=tcpsocket->readAll();
                  ui->textEditRead->append(array);
                      }
                      );
            }
            );

    connect(&timer,&QTimer::timeout,
            [=]()
            {
                timer.stop();
                //发送文件
                senddata();
             }

            );



   void (clintwidget::*funSing)()=&clintwidget::mySignal;
   connect(&w,funSing,this,&severWidget::subprocess);


}

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

void severWidget::on_buttonsend_clicked()
{
    if(NULL==tcpsocket)
    {
        return;
    }

    //获取编辑区内容
    QString str =ui->textEditWrite->toPlainText();
    //将内容发出去
    tcpsocket->write(str.toUtf8().data());
}

void severWidget::on_pushButton_2_clicked()
{
    if(NULL==tcpsocket)
    {
        return;
    }
    //主动和客户端断开连接
    tcpsocket->disconnectFromHost();
    tcpsocket->close();
}

void severWidget::on_change_clicked()
{
    this->close();
    w.show();

}

void severWidget::subprocess(void)
{
    this->show();
    w.hide();
}

void severWidget::on_buttonfile_clicked()
{
    QString filepath =QFileDialog::getOpenFileName(this,"open","../");
    if(false ==filepath.isEmpty())
    {
        filename.clear();
        filesize=0;
        //获取文件信息
        QFileInfo info(filepath);
        filename =info.fileName();
        filesize=info.size();
        sendsize=0;
        //只读打开
        //指定名字
        //打开文件
                file.setFileName(filepath);
                bool isok=file.open(QIODevice::ReadOnly);
                if(false==isok)
                {
                    qDebug()<<"打开失败";
                    ui->buttonfile->setEnabled(true);
                    ui->buttonsend_2->setEnabled(false);
                }
                ui->textEditRead->append(filepath);
                ui->buttonsend_2->setEnabled(true);



    }
    else
    {
        qDebug()<<"路径文件错误";
    }


}
//发送文件按钮
void severWidget::on_buttonsend_2_clicked()
{
    //发送文件头
    QString head =QString("%1##%2").arg(filename).arg(filesize);
    //发送头部信息

    qint64 len =tcpsocket->write(head.toUtf8());
    if(len>0)
    {
        //发送文件
        //防止TCP连包问题
        //需要延时
        timer.start(20);

    }
    else
    {
        qDebug()<<"头部信息发送失败";
        file.close();
        ui->buttonfile->setEnabled(true);
        ui->buttonsend_2->setEnabled(false);

    }

}

void severWidget::senddata()
{
    qint64 len=0;
    do
    {
        //每次发送4K
        char buf[1024*4]={0};
        len=0;
        len=file.read(buf,sizeof(buf));
        //发送数据
        tcpsocket->write(buf,len);
        sendsize+=len;


    }while(len>0);

    //是否发送完毕
    if(sendsize==filesize)
    {
        ui->textEditRead->append("文件发送完毕");
        file.close();
    }

}


QString severWidget::getIP() //获取ip地址
{
    QList<QHostAddress> list =QNetworkInterface::allAddresses();
    foreach (QHostAddress address, list)
    {
       if(address.protocol() ==QAbstractSocket::IPv4Protocol)
           //我们使用IPv4地址
           return address.toString();
    }
    return 0;
}

客户端:

#ifndef CLINTWIDGET_H
#define CLINTWIDGET_H

#include <QWidget>
#include <QTcpSocket>// 通信套接字
#include <QFile>
namespace Ui {
class clintwidget;
}

class clintwidget : public QWidget
{
    Q_OBJECT

public:
    explicit clintwidget(QWidget *parent = 0);
    ~clintwidget();
    QTcpSocket *tcpsocket;
    QString getIP() ;
private slots:
    void on_buttonconnect_clicked();

    void on_pushButton_4_clicked();

    void on_pushButton_2_clicked();

    void on_pushButton_3_clicked();

    void on_linkstate_clicked();

signals:
//信号只能由singal声明
//信号可以重载
    void mySignal();

public slots:
    void sendSignal();


private:
    Ui::clintwidget *ui;
    qint64 clintstate;//反映当前客户端所处状态
    QFile file;
    QString filename;
    qint64 filesize;
    qint64 recvsize;//已发大小
    bool isstart;

};

#endif // CLINTWIDGET_H
#include "clintwidget.h"
#include "ui_clintwidget.h"
#include <QHostAddress>
#include <QMessageBox>


clintwidget::clintwidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::clintwidget)
{
    ui->setupUi(this);
    setWindowTitle("客户端");
    clintstate=0;
    tcpsocket=NULL;
    isstart=true;
    //分配空间
    tcpsocket=new QTcpSocket(this);

    connect(tcpsocket,&QTcpSocket::connected,
            [=]()
             {
                  ui->textEditread->setText("成功连接服务器");
              }
                );

    connect(tcpsocket,&QTcpSocket::readyRead,
            [=]()
            {
                 //获取内容
 //
        if(clintstate==0)
        {
          QByteArray array=tcpsocket->readAll();
          ui->textEditread->append(array);
        }
                 else
                 {
                     QByteArray buf=tcpsocket->readAll();
                     if(isstart==true)
                     {
                         isstart=false;
                         //解析头部信息
                         filename=QString(buf).section("##",0,0);
                         filesize=QString(buf).section("##",1,1).toInt();
                         qDebug()<<filesize;
                         recvsize=0;

                         file.setFileName(filename);
                         bool isok=file.open(QIODevice::WriteOnly);
                         if(isok==false)
                         {
                             qDebug()<<filename;
                             qDebug()<<"open error";
                         }

                     }
                     else
                     {
                         qint64 len= file.write(buf);
                         recvsize+=len;
                         ui->progressBar->setValue(100*double(recvsize)/filesize);
                         if(recvsize==filesize)
                         {
                             file.close();
                             QMessageBox::information(this,"success","文件接收完成");
                             isstart=true;
                         }

                     }

                 }




                 }
            );





}

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

void clintwidget::on_buttonconnect_clicked()
{
    //获取服务器
    QString ip=ui->lineEditip->text();
    qint16 port=ui->lineEditport->text().toInt();

    //主动连接服务器
    tcpsocket->connectToHost(QHostAddress(ip),port);


}

void clintwidget::on_pushButton_4_clicked()
{
    //获取内容
    QString str =ui->textEditwrite->toPlainText();
    //发送数据
    tcpsocket->write(str.toUtf8().data());


}

void clintwidget::on_pushButton_2_clicked()
{
    //主动断开
    tcpsocket->disconnectFromHost();
}

void clintwidget::sendSignal()
{
    emit mySignal();
}

void clintwidget::on_pushButton_3_clicked()
{
    sendSignal();
}

void clintwidget::on_linkstate_clicked()
{
    clintstate=!clintstate;
    if(clintstate==0)
    {
        ui->linkstate->setText("文本接收");
    }
    else
    {
        ui->linkstate->setText("文件接收");
    }
}

(三)简单的TCP/UDP知识

相对于UDP协议TCP相对复杂
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

(四)效果展示

测试:

1.两个端口实现文本互传

在这里插入图片描述

在这里插入图片描述

2.两台电脑之间通过网络实现文件互传

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
传输完成后在应用程序的同级目录产生传输完成后的文件

下面是源码和应用程序的链接:

QT网络调试软件程序及源码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

与光同程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值