最近使用Qt实现一个C/S的应用,结构比较有意思,相信很多人做过C/S的应用,也已经有很多成熟的架构。但是我这个东西还是不一样的。
我们公司有成熟的服务器产品,基于B/S的,SOA结构,浏览器富客户端的应用。我想直接使用这个服务器产品,采用一个相对成熟的产品对我来说有几点好处:一是不需要考虑并发,已有的成熟的产品在并发性能上还是比较稳定的;二是不需要封转服务器端,服务器产品公司会更新和维护,节约大量的成本。
对于我目前从事的行业来说,大多数的应用是基于QT的,很少有浏览器的应用,所以需要封装一个基于Qt的客户端SDK。
所以就有了今天的应用,使用Qt封装一个基于Http协议异步的客户端SDK。
在Qt中直接使用QNetworkAccessManager可以直接进行Http的请求(QHttp已经不被推荐使用),而QNetworkAccessManager的请求和接收数据本身就是异步的。
但是基于QNetworkAccessManager的封装设计着实让我头疼了一个多月。
采用异步对我来说是一个全新的课题,所以一直在看Webkit的源码。
附上一个链接,这篇Blog详细介绍了Webkit的结构:
http://blog.csdn.net/dlmu2001/article/details/6164873
本人设计经验不足,对Qt还有点学艺不精,当时网上也没有一些很详尽的设计参考。
经过一个多月的查找和实践,把一些心得分享给大家。
要点一:对于一个应用程序,一个QNetworkAccessManager就足够了,当然使用多个QNetworkAccessManager也是没有问题的,Webkit中一个QWebpage只会使用一个QNetworkAccessManager。
要点二:每一个回复QNetworkReply都需要删除,否则会出现内存泄露,根据Qt的帮助文档,在接收完数据的槽中使用deleteLater(),防止内存泄露。
先附上设计代码(其实在Qt最新的版本中有很好的例子,大家可以参考Qt的Demo中的例子):
MyNetManager.h
- #ifndef MYNETMANAGER_H_
- #define MYNETMANAGER_H_
-
- #include <QUrl>
- #include <QByteArray>
- class QNetworkAccessManager;
-
- class MyNetManager : public QObject
- {
- Q_OBJECT
- public:
- MyNetManager(QNetworkAccessManager *pManager);
- ~MyNetManager();
- bool get(QUrl url);
- bool post(QUrl url,QByteArray& bytes);
- signals:
- void downloadProgress( qint64 bytesSent, qint64 bytesTotal);
- public slots:
- void finished();
- private:
- QNetworkAccessManager *m_pManager;
- };
-
- #endif
MyNetManager.cpp
- #include "MyNetManager.h"
- #include <QNetworkAccessManager>
- #include <QNetworkReply>
- #include <QNetworkRequest>
-
- MyNetManager::MyNetManager( QNetworkAccessManager *pManager )
- :m_pManager(pManager)
- {}
-
- MyNetManager::~MyNetManager()
- {}
-
- bool MyNetManager::get( QUrl url )
- {
- QNetworkRequest request;
- request.setUrl(url);
- QNetworkReply *reply = m_pManager->get(request);
- connect(reply, SIGNAL(finished()), this, SLOT(finished()));
- connect(reply, SIGNAL(downloadProgress(qint64,qint64)),this,SIGNAL(downloadProgress(qint64,qint64)));
- return true;
- }
-
- bool MyNetManager::post( QUrl url,QByteArray& bytes )
- {
- QNetworkRequest request;
- request.setUrl(url);
- QNetworkReply *reply = m_pManager->post(request,bytes);
- connect(reply, SIGNAL(finished()), this, SLOT(finished()));
- connect(reply, SIGNAL(downloadProgress(qint64,qint64)),this,SIGNAL(downloadProgress(qint64,qint64)));
- return true;
- }
-
- void MyNetManager::finished()
- {
- QNetworkReply* reply = (QNetworkReply*)sender();
-
- reply->deleteLater();
- }