给公司开发的软件,每次更新后都要一个个的去帮使用的同事重新安装,很麻烦,所以放下几个bug没有解决,先写了一个升级的小程序。
程序入口(main.cpp):
- #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):
- /*
- * 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):
- /*
- * 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的定义和实现():
- /*
- * 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_ */
- /*
- * 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();
- }