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();
}
程序入口(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编写的软件在线升级系统(服务器端)
- Qt编写的软件在线升级系统(服务器端)
- Qt编写的软件在线升级系统(服务器端)
- Qt编写的软件在线升级系统(客户端)
- Qt编写的软件在线升级系统(客户端)
- Qt编写的软件在线升级系统(客户端)
- Qt编写的软件在线升级系统(客户端)
- Qt编写的软件在线升级系统(客户端)
- VB中利用第三方控件实现软件在线升级
- 用C#实现C/S模式下软件自动在线升级
- 用C#实现C/S模式下软件自动在线升级
- 用C#实现C/S模式下软件自动在线升级
- 面对软件错误构建可靠的分布式系统-6编写可容错系统
- 用C# 实现C/S模式下软件自动在线升级
- 软件包管理 之 软件在线升级更新yum 图形工具介绍
- [转] 用C#实现C/S模式下软件自动在线升级
- 用C#实现C/S模式下软件自动在线升级
- 软件包管理 之 软件在线升级更新yum 图形工具介绍
- CodeTEST嵌入式软件在线测试与分析工具在嵌入式系统开发中的应用
- 用C#实现C/S模式下软件自动在线升级