接上面,进一步分析QNetworkAccessManager::createRequest()的实现。去除不重要的分支末节,看其调用的QNetworkReplyImplPrivate::setup()和QNetworkAccessManagerPrivate::findBackend()的代码。
void QNetworkReplyImplPrivate::setup(QNetworkAccessManager::Operation op, const QNetworkRequest &req,
QIODevice *data)
{
Q_Q(QNetworkReplyImpl);
outgoingData = data;
request = req;
url = request.url();
operation = op;
if (outgoingData) { // outgoingData实际就是QNetworkRequest对象
q->connect(outgoingData, SIGNAL(readyRead()), SLOT(_q_sourceReadyRead()));
q->connect(outgoingData, SIGNAL(readChannelFinished()), SLOT(_q_sourceReadChannelFinished()));
}
q->QIODevice::open(QIODevice::ReadOnly); // ???
QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection);
}
连接两个信号与槽之后,是打开QIODevice,暂未深入分析。然后是呼叫q->_q_startOperation(),实际就是调用QNetworkReplyImpl::_q_startOperation(),使用的是队列等待方式(也就是发送一个消息进入系统消息队列,这个setup函数以及全部后续执行完毕,主动权交回给Windows后,再根据进入队列的消息来触发)。
因此我们先看QNetworkAccessManagerPrivate::findBackend()的代码实现:
QNetworkAccessBackend *QNetworkAccessManagerPrivate::findBackend(QNetworkAccessManager::Operation op,
const QNetworkRequest &request)
{
QNetworkRequest::CacheLoadControl mode =
static_cast<QNetworkRequest::CacheLoadControl>(
request.attribute(QNetworkRequest::CacheLoadControlAttribute,
QNetworkRequest::PreferNetwork).toInt());
if (mode == QNetworkRequest::AlwaysCache
&& (op == QNetworkAccessManager::GetOperation
|| op == QNetworkAccessManager::HeadOperation)) {
QNetworkAccessBackend *backend = new QNetworkAccessCacheBackend;
backend->manager = this;
return backend;
}
if (!factoryDataShutdown) {
QMutexLocker locker(&factoryData()->mutex);
QNetworkAccessBackendFactoryData::ConstIterator it = factoryData()->constBegin(),
end = factoryData()->constEnd();
while (it != end) {
QNetworkAccessBackend *backend = (*it)->create(op, request);
if (backend) {
backend->manager = this;
return backend; // found a factory that handled our request
}
++it;
}
}
return 0;
}
这段代码有一点复杂,先看红色标记的第一句,factoryData()是用宏来定义的函数:
Q_GLOBAL_STATIC(QNetworkAccessBackendFactoryData, factoryData)
宏定义如下:
#define Q_GLOBAL_STATIC(TYPE, NAME) \
static TYPE *NAME() \
{ \
static TYPE this_##NAME; \
static QGlobalStatic<TYPE > global_##NAME(&this_##NAME); \
return global_##NAME.pointer; \
}
如果对STD比较熟悉,第一感觉这是一个模板List操作。在这里constBegin()和constEnd()组合起来是一个遍历,那么在什么地方设定值呢?良好代码的命名是很规范的,我试了试全局查找factoryData(),找到了我所希望看到的东西:
QNetworkAccessBackendFactory::QNetworkAccessBackendFactory()
{
QMutexLocker locker(&factoryData()->mutex);
factoryData()->prepend(this);
}
QNetworkAccessBackendFactory::~QNetworkAccessBackendFactory()
{
if (!factoryDataShutdown) {
QMutexLocker locker(&factoryData()->mutex);
factoryData()->removeAll(this);
}
}
这里prepend()应该是把对象添加到列表;而removeAll()就是清空全部数据了。
factoryData()里面包含的对象序列,应该是从QNetworkAccessBackendFactory衍生出来的。
一共有哪些子类呢?继续全局查找:
class QNetworkAccessDataBackendFactory: public QNetworkAccessBackendFactory
class QNetworkAccessDebugPipeBackendFactory: public QNetworkAccessBackendFactory
class QNetworkAccessFileBackendFactory: public QNetworkAccessBackendFactory
class QNetworkAccessFtpBackendFactory: public QNetworkAccessBackendFactory
class QNetworkAccessHttpBackendFactory : public QNetworkAccessBackendFactory
去除暂时不关心的DebugPipe,一共有四种:DataBackend、FileBackend、FtpBackend、HttpBackend。媒体的种类原来是在这里实现的。看其中QNetworkAccessHttpBackendFactory::create()
QNetworkAccessBackend *
QNetworkAccessHttpBackendFactory::create(QNetworkAccessManager::Operation op,
const QNetworkRequest &request) const
{
// check the operation
switch (op) {
case QNetworkAccessManager::GetOperation:
case QNetworkAccessManager::PostOperation:
case QNetworkAccessManager::HeadOperation:
case QNetworkAccessManager::PutOperation:
break;
default:
// no, we can't handle this request
return 0;
}
QUrl url = request.url();
QString scheme = url.scheme().toLower();
if (scheme == QLatin1String("http") || scheme == QLatin1String("https"))
return new QNetworkAccessHttpBackend;
return 0;
}
如果是能够处理的OP标记并且URL的前缀是http或者是https,则创建一个QNetworkAccessHttpBackend对象。
前面QNetworkAccessManager::get()代码中,调用的参数是QNetworkAccessManager::GetOperation,所以在我们分析的这个应用中,创建的是QNetworkAccessHttpBackend对象。
findBackend()到此分析完毕;由于factoryData()的具体实现跟我们分析网络通信的目标没有太大关系,未深入分析,有谁分析了的话请转告一声,值得一看。
回到前面暂停的QNetworkReplyImpl::_q_startOperation(),又实现了什么动作呢?
void QNetworkReplyImplPrivate::_q_startOperation()
{
// This function is called exactly once
state = Working;
if (!backend) {
error(QNetworkReplyImpl::ProtocolUnknownError,
QCoreApplication::translate("QNetworkReply", "Protocol \"%1\" is unknown").arg(url.scheme())); // not really true!;
finished();
return;
}
backend->open();
if (state != Finished) {
if (operation == QNetworkAccessManager::GetOperation)
pendingNotifications.append(NotifyDownstreamReadyWrite);
if (outgoingData) {
_q_sourceReadyRead();
}
handleNotifications();
}
}
首先调用了刚刚创建的QNetworkAccessHttpBackend::open(),然后是添加通知消息、调用_q_sourceReadyRead()、最后处理通知消息。
void QNetworkReplyImplPrivate::setup(QNetworkAccessManager::Operation op, const QNetworkRequest &req,
QIODevice *data)
{
Q_Q(QNetworkReplyImpl);
outgoingData = data;
request = req;
url = request.url();
operation = op;
if (outgoingData) { // outgoingData实际就是QNetworkRequest对象
q->connect(outgoingData, SIGNAL(readyRead()), SLOT(_q_sourceReadyRead()));
q->connect(outgoingData, SIGNAL(readChannelFinished()), SLOT(_q_sourceReadChannelFinished()));
}
q->QIODevice::open(QIODevice::ReadOnly); // ???
QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection);
}
连接两个信号与槽之后,是打开QIODevice,暂未深入分析。然后是呼叫q->_q_startOperation(),实际就是调用QNetworkReplyImpl::_q_startOperation(),使用的是队列等待方式(也就是发送一个消息进入系统消息队列,这个setup函数以及全部后续执行完毕,主动权交回给Windows后,再根据进入队列的消息来触发)。
因此我们先看QNetworkAccessManagerPrivate::findBackend()的代码实现:
QNetworkAccessBackend *QNetworkAccessManagerPrivate::findBackend(QNetworkAccessManager::Operation op,
const QNetworkRequest &request)
{
QNetworkRequest::CacheLoadControl mode =
static_cast<QNetworkRequest::CacheLoadControl>(
request.attribute(QNetworkRequest::CacheLoadControlAttribute,
QNetworkRequest::PreferNetwork).toInt());
if (mode == QNetworkRequest::AlwaysCache
&& (op == QNetworkAccessManager::GetOperation
|| op == QNetworkAccessManager::HeadOperation)) {
QNetworkAccessBackend *backend = new QNetworkAccessCacheBackend;
backend->manager = this;
return backend;
}
if (!factoryDataShutdown) {
QMutexLocker locker(&factoryData()->mutex);
QNetworkAccessBackendFactoryData::ConstIterator it = factoryData()->constBegin(),
end = factoryData()->constEnd();
while (it != end) {
QNetworkAccessBackend *backend = (*it)->create(op, request);
if (backend) {
backend->manager = this;
return backend; // found a factory that handled our request
}
++it;
}
}
return 0;
}
这段代码有一点复杂,先看红色标记的第一句,factoryData()是用宏来定义的函数:
Q_GLOBAL_STATIC(QNetworkAccessBackendFactoryData, factoryData)
宏定义如下:
#define Q_GLOBAL_STATIC(TYPE, NAME) \
static TYPE *NAME() \
{ \
static TYPE this_##NAME; \
static QGlobalStatic<TYPE > global_##NAME(&this_##NAME); \
return global_##NAME.pointer; \
}
如果对STD比较熟悉,第一感觉这是一个模板List操作。在这里constBegin()和constEnd()组合起来是一个遍历,那么在什么地方设定值呢?良好代码的命名是很规范的,我试了试全局查找factoryData(),找到了我所希望看到的东西:
QNetworkAccessBackendFactory::QNetworkAccessBackendFactory()
{
QMutexLocker locker(&factoryData()->mutex);
factoryData()->prepend(this);
}
QNetworkAccessBackendFactory::~QNetworkAccessBackendFactory()
{
if (!factoryDataShutdown) {
QMutexLocker locker(&factoryData()->mutex);
factoryData()->removeAll(this);
}
}
这里prepend()应该是把对象添加到列表;而removeAll()就是清空全部数据了。
factoryData()里面包含的对象序列,应该是从QNetworkAccessBackendFactory衍生出来的。
一共有哪些子类呢?继续全局查找:
class QNetworkAccessDataBackendFactory: public QNetworkAccessBackendFactory
class QNetworkAccessDebugPipeBackendFactory: public QNetworkAccessBackendFactory
class QNetworkAccessFileBackendFactory: public QNetworkAccessBackendFactory
class QNetworkAccessFtpBackendFactory: public QNetworkAccessBackendFactory
class QNetworkAccessHttpBackendFactory : public QNetworkAccessBackendFactory
去除暂时不关心的DebugPipe,一共有四种:DataBackend、FileBackend、FtpBackend、HttpBackend。媒体的种类原来是在这里实现的。看其中QNetworkAccessHttpBackendFactory::create()
QNetworkAccessBackend *
QNetworkAccessHttpBackendFactory::create(QNetworkAccessManager::Operation op,
const QNetworkRequest &request) const
{
// check the operation
switch (op) {
case QNetworkAccessManager::GetOperation:
case QNetworkAccessManager::PostOperation:
case QNetworkAccessManager::HeadOperation:
case QNetworkAccessManager::PutOperation:
break;
default:
// no, we can't handle this request
return 0;
}
QUrl url = request.url();
QString scheme = url.scheme().toLower();
if (scheme == QLatin1String("http") || scheme == QLatin1String("https"))
return new QNetworkAccessHttpBackend;
return 0;
}
如果是能够处理的OP标记并且URL的前缀是http或者是https,则创建一个QNetworkAccessHttpBackend对象。
前面QNetworkAccessManager::get()代码中,调用的参数是QNetworkAccessManager::GetOperation,所以在我们分析的这个应用中,创建的是QNetworkAccessHttpBackend对象。
findBackend()到此分析完毕;由于factoryData()的具体实现跟我们分析网络通信的目标没有太大关系,未深入分析,有谁分析了的话请转告一声,值得一看。
回到前面暂停的QNetworkReplyImpl::_q_startOperation(),又实现了什么动作呢?
void QNetworkReplyImplPrivate::_q_startOperation()
{
// This function is called exactly once
state = Working;
if (!backend) {
error(QNetworkReplyImpl::ProtocolUnknownError,
QCoreApplication::translate("QNetworkReply", "Protocol \"%1\" is unknown").arg(url.scheme())); // not really true!;
finished();
return;
}
backend->open();
if (state != Finished) {
if (operation == QNetworkAccessManager::GetOperation)
pendingNotifications.append(NotifyDownstreamReadyWrite);
if (outgoingData) {
_q_sourceReadyRead();
}
handleNotifications();
}
}
首先调用了刚刚创建的QNetworkAccessHttpBackend::open(),然后是添加通知消息、调用_q_sourceReadyRead()、最后处理通知消息。