您的位置:首页 > 编程语言 > Qt开发

Qt编写的软件在线升级系统(服务器端)

2014-09-12 17:09 423 查看
给公司开发的软件,每次更新后都要一个个的去帮使用的同事重新安装,很麻烦,所以放下几个bug没有解决,先写了一个升级的小程序。

 

程序入口(main.cpp):

[cpp] view
plaincopy

#include <QtCore>  

#include <QCoreApplication>  

#include <QDebug>  

#include <QTextCodec>  

#include "Server.h"  

int main(int argc, char *argv[])  

{  

    QCoreApplication a(argc, argv);  

    QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));  

    QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));  

    qDebug()<<"CR_MRP_update:Welcome to ChuangRen MRP/nCR_MRP_Update:Update Server starting...";  

    Server *server=new Server();  

    server->listenConnect();  

    return a.exec();  

}  

 

在主程序中先设置了软件的编码,然后启动一个服务器并监听连接。服务器类的定义如下(Server.h):

 

[cpp] view
plaincopy

/* 

 * Server.h 

 * 

 *  Created on: 2009-5-7 

 *      Author: 于成文 

 */  

#ifndef SERVER_H_  

#define SERVER_H_  

#include <QDebug>  

#include <QTcpServer>  

#include <QTcpSocket>  

#include <QHostAddress>  

#include <QFile>  

#include <QByteArray>  

#include "ConnectThread.h"  

class Server : public QTcpServer{  

    Q_OBJECT  

public:  

    Server(QObject *parent=0);  

    ~Server();  

    bool listenConnect();  

private slots:  

    void incomingConnection(int socketId);  

private:  

    QString version;    //服务器上的最新版本  

    QByteArray file1,file2; //保存客户端要更新的文件  

};  

#endif /* SERVER_H_ */  

 

下面是Server类的实现(Server.cpp):

 

[cpp] view
plaincopy

/* 

 * Server.cpp 

 * 

 *  Created on: 2009-5-7 

 *      Author: 于成文 

 */  

#include "Server.h"  

Server::Server(QObject *parent):QTcpServer(parent)  

{  

    QFile file("version.dat");  

    if (file.open(QIODevice::ReadOnly))  

    {  

        QTextStream stream(&file);  

        version = stream.readLine();  

        file.close();  

    }  

    QFile upfile1("MRP.exe");  

    QFile upfile2("common.dll");  

    if (upfile1.open(QIODevice::ReadOnly)&&upfile2.open(QIODevice::ReadOnly))  

    {  

        file1=upfile1.readAll();  

        file2=upfile2.readAll();  

    }  

}  

Server::~Server() {  

}  

/** 

 * 开始监听 

 */  

bool Server::listenConnect()  

{  

    if(!this->listen(QHostAddress::Any,3327))  

    {  

        qDebug()<<"CR_MRP_Update:listen on port 3327 failed!";  

        this->close();  

        return false;  

    }  

    qDebug()<<"CR_MRP_Update:listen on port 3327,waiting connection...";  

    return true;  

}  

/** 

 * 当有客户端连接时运行此函数 

 */  

void Server::incomingConnection(int socketId)  

{  

    qDebug()<<"/nCR_MRP_Update:a client try to connect...";  

    //连接客户端  

    ConnectThread * thread = new ConnectThread(this,socketId,version,file1,file2);  

}  

 

在Server类的构造函数中读取了当前服务器上的客户端软件的版本信息,并将客户端读入内存。当有客户端连接是会自动运行函数incomingConnection(int socketId),这个函数中初始化了一个ConnectThread类的对象,并将各种信息通过构造函数传递给它。

下面是类ConnectThread的定义和实现():

 

[cpp] view
plaincopy

/* 

 * ConnectThread.h 

 * 

 *  Created on: 2009-5-7 

 *      Author: 于成文 

 */  

#ifndef CONNECTTHREAD_H_  

#define CONNECTTHREAD_H_  

#include <QDebug>  

#include <QTcpSocket>  

#include <QDataStream>  

#include <QDate>  

#include <QByteArray>  

#include <QFile>  

class ConnectThread : public QObject  

{  

    Q_OBJECT  

public:  

    ConnectThread(QObject * parent = 0 ,int socketId=0,const QString &version="",QByteArray file1=0,QByteArray file2=0);  

    ~ConnectThread();  

private:  

    int socketId;  

    QTcpSocket *clientSocket;  

    quint64 nextBlockSize;  

    QString version;  

    QByteArray file1,file2;  

private slots:  

    void threadOver();  

    void communicate();  

};  

#endif /* CONNECTTHREAD_H_ */  

 

 

[cpp] view
plaincopy

/* 

 * ConnectThread.cpp 

 * 

 *  Created on: 2009-5-7 

 *      Author: 于成文 

 */  

#include "ConnectThread.h"  

ConnectThread::ConnectThread(QObject * parent,int socketId,const QString &version,QByteArray file1,QByteArray file2)  

{  

    nextBlockSize=0;  

    clientSocket=new QTcpSocket(this);  

    clientSocket->setSocketDescriptor(socketId);  

    this->version=version;  

    this->file1=file1;  

    this->file2=file2;  

    connect(clientSocket, SIGNAL(disconnected()),this, SLOT(threadOver()));  

    connect(clientSocket,SIGNAL(readyRead()),this,SLOT(communicate()));  

    qDebug()<<"CR_MRP_Update:connect to server successful,client id is"<<socketId;  

    //发送当前服务器上的客户端版本信息给升级客户端  

    QByteArray block;  

    QDataStream out(&block, QIODevice::WriteOnly);  

    out.setVersion(QDataStream::Qt_4_5);  

    out<<quint64(0)<<quint16(0x0001)<<version;  

    out.device()->seek(0);  

    out<<quint64(block.size()-sizeof(quint16));  

    clientSocket->write(block);  

}  

ConnectThread::~ConnectThread() {  

}  

/** 

 * 和客户端通信 

 */  

void ConnectThread::communicate()  

{  

    //创建数据流  

    QDataStream in(clientSocket);  

    in.setVersion(QDataStream::Qt_4_5);  

    while(1)  

    {  

        if (nextBlockSize == 0)  

        {  

            if (clientSocket->bytesAvailable() < sizeof(quint64))  

            {  

                break;  

            }  

            in >> nextBlockSize;  

        }  

        if ((quint64)(clientSocket->bytesAvailable())<nextBlockSize)  

        {  

            break;;  

        }  

        quint16 protocol;  

        in>>protocol;  

        qDebug()<<"CR_MRP_Update:protocol:"<<QString::number(protocol,16);  

        if(protocol==1)  

        {  

            //升级  

            QByteArray fblock;  

            QDataStream fout(&fblock, QIODevice::WriteOnly);  

            fout.setVersion(QDataStream::Qt_4_5);  

            fout<<quint64(0)<<quint16(0x0002)<<file1<<file2;  

            fout.device()->seek(0);  

            fout<<quint64(fblock.size()-sizeof(quint64));  

            clientSocket->write(fblock);  

            qDebug()<<"CR_MRP_Update:size:"<<QString::number(fblock.size()-sizeof(quint64));  

        }  

        nextBlockSize=0;  

    }  

}  

/** 

 * 释放网络连接资源 

 */  

void ConnectThread::threadOver()  

{  

    qDebug()<<"CR_MRP_Update:a client connection closed.../n";  

    clientSocket->deleteLater();  

    this->deleteLater();  

}  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  qt C++ 服务器