Qt UDP传送图片

Qt UDP传送图片,server发送,client接收。

 server

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QTime>
#include <QPainter>

#define TRAN_SIZE 1024;
struct ImageFrameHead
{
    int funCode;                        //!功能码
    unsigned int uTransFrameHdrSize;    //!sizeof(WIFI_FRAME_HEADER)
    unsigned int uTransFrameSize;       //!sizeof(WIFI_FRAME_HEADER) + Data Size

    //数据帧变量
    unsigned int uDataFrameSize;        //数据帧的总大小
    unsigned int uDataFrameTotal;       //一帧数据被分成传输帧的个数
    unsigned int uDataFrameCurr;        //数据帧当前的帧号
    unsigned int uDataInFrameOffset;    //数据帧在整帧的偏移
};

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    QFont font;
    font.setPixelSize(16);
    setFont(font);
    setWindowTitle(QStringLiteral("UDP Server"));
    ui->label->setMaximumHeight(ui->pushButton->sizeHint().height());

    mUdpSocket = new QUdpSocket(this);
}

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

void MainWindow::closeEvent(QCloseEvent *event)
{
    Q_UNUSED(event);

    mFlag = true;
    mUdpSocket->close();
}

void MainWindow::on_pushButton_clicked()
{
    QString name;
    int sendCount = 1;
    int size = 0;
    int num = 0;
    int count = 0;
    int endSize = 0;
    ImageFrameHead mes;
    while(1)
    {
        name = QStringLiteral("./data/%1.jpg").arg(sendCount, 3, 10, QLatin1Char('0'));
        mFile.setFileName(name);
        mFile.open(QIODevice::ReadOnly);
        char *m_sendBuf = new char[1024];

        size = mFile.size();
        num = 0;
        count = 0;
        endSize = size%996;
        if (endSize == 0)
        {
            num = size/996;
        }
        else
        {
            num = size/996+1;
        }

        while (count < num)
        {
            memset(m_sendBuf, 0, 1024);

            mes.funCode = 24;
            mes.uTransFrameHdrSize = sizeof(ImageFrameHead);
            if ((count+1) != num)
            {
                mes.uTransFrameSize = 996;
            }
            else
            {
                mes.uTransFrameSize = endSize;
            }

            mes.uDataFrameSize = size;
            mes.uDataFrameTotal = num;
            mes.uDataFrameCurr = count+1;
            mes.uDataInFrameOffset = count*(1024 - sizeof(ImageFrameHead));

            mFile.read(m_sendBuf+sizeof(ImageFrameHead), 1024-sizeof(ImageFrameHead));
            memcpy(m_sendBuf, (char *)&mes, sizeof(ImageFrameHead));
            mUdpSocket->writeDatagram(m_sendBuf, mes.uTransFrameSize+mes.uTransFrameHdrSize, QHostAddress("127.0.0.1"), 9930);

            QTime dieTime = QTime::currentTime().addMSecs(1);
            while( QTime::currentTime() < dieTime )
            {
                QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
            }
            qDebug() << "";

            count++;
        }

        delete []m_sendBuf;

        QTime dieTime = QTime::currentTime().addMSecs(10);
        while( QTime::currentTime() < dieTime )
        {
            QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
        }

        ui->label->setText(QStringLiteral("%1").arg(sendCount++));

        if (sendCount == mMaxFileNum + 1)
        {
            sendCount = 1;
        }

        mFile.close();

        if (mFlag)
        {
            break;
        }
    }
}

void MainWindow::on_pushButton_2_clicked()
{
    QImage image("wintersun.jpg");
    QImage image2(image.size(), QImage::Format_ARGB32);

    for (int i = 1; i <= mMaxFileNum; ++i)
    {
        QString name = QStringLiteral("%1").arg(i, 3, 10, QLatin1Char('0'));
        QPainter painter(&image2);
        painter.drawImage(0, 0, image);
        QPen pen(Qt::red);
        QFont font("微软雅黑", 30, QFont::Bold);
        painter.setPen(pen);
        painter.setFont(font);
        painter.drawText(30, 50, name);

        image2.save(QStringLiteral("./data/%1.jpg").arg(name), "jpg", 100);
        ui->label_image->setPixmap(QPixmap::fromImage(image2));
        QCoreApplication::processEvents(QEventLoop::AllEvents);
    }
}

client

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QThread>
#include <QUdpSocket>
struct ImageFrameHead
{
    int funCode;                        //!功能码
    unsigned int uTransFrameHdrSize;    //!sizeof(WIFI_FRAME_HEADER)
    unsigned int uTransFrameSize;       //!sizeof(WIFI_FRAME_HEADER) + Data Size

    //数据帧变量
    unsigned int uDataFrameSize;        //数据帧的总大小
    unsigned int uDataFrameTotal;       //一帧数据被分成传输帧的个数
    unsigned int uDataFrameCurr;        //数据帧当前的帧号
    unsigned int uDataInFrameOffset;    //数据帧在整帧的偏移
};

class UdpThread : public QThread
{
    Q_OBJECT

public:
    explicit UdpThread(QObject *parent = 0);
    ~UdpThread();

protected:
    virtual void run();

signals:
    void sigRecvOk(char *buf, int len);

public slots:
    void slotRecv();

private:
    QUdpSocket *m_udpSocket;
    char *m_buf;
};

UdpThread::UdpThread(QObject *parent) :
    QThread(parent)
{
    m_buf = new char[1024*1024];
    memset(m_buf, 0, 1024*1024);
}

UdpThread::~UdpThread()
{
    m_udpSocket->close();
    delete []m_buf;
}

void UdpThread::run()
{
    m_udpSocket = new QUdpSocket;
    connect(m_udpSocket, SIGNAL(readyRead()), this, SLOT(slotRecv()), Qt::DirectConnection);
    m_udpSocket->bind(QHostAddress("127.0.0.1"), 9930);
    exec();
}

void UdpThread::slotRecv()
{
    char *recvBuf = new char[1052];
    memset(recvBuf, 0, 1052);
    while(m_udpSocket->hasPendingDatagrams())
    {
        memset(recvBuf, 0, 1052);
        int size = m_udpSocket->pendingDatagramSize();
        m_udpSocket->readDatagram(recvBuf, size);

        ImageFrameHead *mes = (ImageFrameHead *)recvBuf;
        if (mes->funCode == 24) {
            memcpy(m_buf+mes->uDataInFrameOffset, (recvBuf+ sizeof(ImageFrameHead)), mes->uTransFrameSize);
            if (mes->uDataFrameCurr == mes->uDataFrameTotal)
            {
                emit sigRecvOk(m_buf, mes->uDataFrameSize);
            }
        }
    }

    delete []recvBuf;
}

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    QFont font;
    font.setPixelSize(16);
    setFont(font);
    setWindowTitle(QStringLiteral("UDP client"));

    m_udpThread = new UdpThread;
    connect(m_udpThread, SIGNAL(sigRecvOk(char*,int)), this, SLOT(slotRecv(char*,int)));
}

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

void MainWindow::on_pushButton_clicked()
{
    m_udpThread->start();
}

void MainWindow::closeEvent(QCloseEvent *event)
{
    Q_UNUSED(event);

    if (m_udpThread->isRunning())
    {
        m_udpThread->quit();
    }
}

void MainWindow::slotRecv(char * buf, int len)
{
    QPixmap pixmap;
    pixmap.loadFromData((uchar*)buf, len, "JPG");
    ui->label->setPixmap(pixmap);
}
Qt 是一个强大的跨平台应用程序开发框架,它提供了丰富的图形用户界面工具和网络通信功能,包括与 TFTP(Trivial File Transfer Protocol)服务器的交互。要在 Qt 应用中实现向 TFTP 服务器上传文件,你需要遵循以下步骤: 1. 引入所需库:首先,确保你的项目包含了 Qt 的网络模块(QtNetwork),因为 TFTP 通信是在这个模块中处理的。 ```cpp #include <QObject> #include <QHostAddress> #include <QUdpSocket> #include <QNetworkAccessManager> #include <QNetworkRequest> ``` 2. 创建 UDP 会话:使用 `QUdpSocket` 类创建一个 UDP 套接字来发送数据到 TFTP 服务器。 ```cpp QUdpSocket *udpSocket = new QUdpSocket(this); if (!udpSocket->bind(0)) { // 处理绑定失败 } ``` 3. 发起 TFTP 请求:使用 `QNetworkAccessManager` 实现 TFTP 的 GET 或 PUT 请求。对于上传文件,通常会使用 PUT 方法。 ```cpp QNetworkAccessManager *manager = new QNetworkAccessManager(this); QNetworkRequest request(QUrl(QStringLiteral("tftp://<server_ip>/<file_path>"))); request.setRawHeader("Method", "PUT"); // 设置请求方法为 PUT connect(manager, &QNetworkAccessManager::finished, this, &YourClass::handleTftpResponse); manager->put(request, QByteArray()); ``` 4. 处理响应:在 `handleTftpResponse` 函数中检查上传状态并处理返回的数据。 ```cpp void YourClass::handleTftpResponse(QNetworkReply *reply) { if (reply->error()) { // 处理错误 } else { QByteArray data = reply->readAll(); // 检查数据确认上传完成或处理错误 } reply->deleteLater(); } ``` 5. 数据分块传输:由于 TFTP 是基于文本协议的,如果文件较大,可能需要分块传输。你可以使用循环或生成器函数来逐块读取并发送数据。 6. 关闭连接:上传完成后,记得关闭 UDP 套接字和网络访问管理器。 ```cpp udpSocket->close(); delete udpSocket; ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值