voidQAbstractSocketPrivate::connectionNotification(){// If in connecting state, check if the connection has been// established, otherwise flush pending data._q_testConnection();}
voidQAbstractSocketPrivate::_q_connectToNextAddress(){Q_Q(QAbstractSocket);do{// Check for more pending addressesif(addresses.isEmpty()){
state = QAbstractSocket::UnconnectedState;
emit q->stateChanged(state);
emit q->error(socketError);return;}}
voidQHttpNetworkConnectionChannel::init(){
socket =new QTcpSocket;// After some back and forth in all the last years, this is now a DirectConnection because otherwise// the state inside the *Socket classes gets messed up, also in conjunction with the socket notifiers// which behave slightly differently on Windows vs LinuxQObject::connect(socket,SIGNAL(bytesWritten(qint64)),this,SLOT(_q_bytesWritten(qint64)),
Qt::DirectConnection);QObject::connect(socket,SIGNAL(connected()),this,SLOT(_q_connected()),
Qt::DirectConnection);QObject::connect(socket,SIGNAL(readyRead()),this,SLOT(_q_readyRead()),
Qt::DirectConnection);// The disconnected() and error() signals may already come// while calling connectToHost().// In case of a cached hostname or an IP this// will then emit a signal to the user of QNetworkReply// but cannot be caught because the user did not have a chance yet// to connect to QNetworkReply's signals.
qRegisterMetaType<QAbstractSocket::SocketError>();QObject::connect(socket,SIGNAL(disconnected()),this,SLOT(_q_disconnected()),
Qt::DirectConnection);QObject::connect(socket,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(_q_error(QAbstractSocket::SocketError)),
Qt::DirectConnection);
voidQHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socketError){if(!socket)return;
QNetworkReply::NetworkError errorCode = QNetworkReply::UnknownNetworkError;switch(socketError){case QAbstractSocket::HostNotFoundError:
errorCode = QNetworkReply::HostNotFoundError;break;case QAbstractSocket::ConnectionRefusedError:
errorCode = QNetworkReply::ConnectionRefusedError;break;case QAbstractSocket::RemoteHostClosedError:}elseif(state == QHttpNetworkConnectionChannel::ReadingState){if(reply->contentLength()==-1&&!reply->d_func()->isChunked()){_q_receiveReply();}
errorCode = QNetworkReply::RemoteHostClosedError;}else{
errorCode = QNetworkReply::RemoteHostClosedError;}break;case QAbstractSocket::SocketTimeoutError:// try to reconnect/resend before sending an error.
errorCode = QNetworkReply::TimeoutError;break;case QAbstractSocket::ProxyAuthenticationRequiredError:
errorCode = QNetworkReply::ProxyAuthenticationRequiredError;break;case QAbstractSocket::SslHandshakeFailedError:
errorCode = QNetworkReply::SslHandshakeFailedError;break;case QAbstractSocket::ProxyConnectionClosedError:
errorCode = QNetworkReply::ProxyConnectionClosedError;break;case QAbstractSocket::ProxyConnectionTimeoutError:
errorCode = QNetworkReply::ProxyTimeoutError;break;default:// all other errors are treated as NetworkError
errorCode = QNetworkReply::UnknownNetworkError;break;}
QPointer<QHttpNetworkConnection> that = connection;
QString errorString = connection->d_func()->errorDetail(errorCode, socket, socket->errorString());// emit error for all waiting repliesdo{// Need to dequeu the request so that we can emit the error.if(!reply)
connection->d_func()->dequeueRequest(socket);if(reply){
reply->d_func()->errorString = errorString;
emit reply->finishedWithError(errorCode, errorString);
reply =0;if(protocolHandler)
protocolHandler->setReply(0);}}while(!connection->d_func()->highPriorityQueue.isEmpty()||!connection->d_func()->lowPriorityQueue.isEmpty());
voidQNetworkReplyHttpImplPrivate::postRequest(const QNetworkRequest &newHttpRequest){Q_Q(QNetworkReplyHttpImpl);
QThread *thread =0;if(synchronous){// A synchronous HTTP request uses its own thread
thread =newQThread();QObject::connect(thread,SIGNAL(finished()), thread,SLOT(deleteLater()));
thread->start();}else{
thread = managerPrivate->createThread();}auto redirectPolicy = QNetworkRequest::ManualRedirectPolicy;
httpRequest.setRedirectPolicy(redirectPolicy);switch(operation){case QNetworkAccessManager::GetOperation:
httpRequest.setOperation(QHttpNetworkRequest::Get);if(loadFromCacheIfAllowed(httpRequest))return;// no need to send the request! :)break;case QNetworkAccessManager::PostOperation:invalidateCache();
httpRequest.setOperation(QHttpNetworkRequest::Post);createUploadByteDevice();break;default:break;// can't happen}if(newHttpRequest.attribute(QNetworkRequest::HttpPipeliningAllowedAttribute).toBool())
httpRequest.setPipeliningAllowed(true);// Create the HTTP thread delegate
QHttpThreadDelegate *delegate =new QHttpThreadDelegate;// For the synchronous HTTP, this is the normal way the delegate gets deleted// For the asynchronous HTTP this is a safety measure, the delegate deletes itself when HTTP is finishedQObject::connect(thread,SIGNAL(finished()), delegate,SLOT(deleteLater()));// Do we use synchronous HTTP?
delegate->synchronous = synchronous;if(!synchronous){// Tell our zerocopy policy to the delegate
QVariant downloadBufferMaximumSizeAttribute = newHttpRequest.attribute(QNetworkRequest::MaximumDownloadBufferSizeAttribute);if(downloadBufferMaximumSizeAttribute.isValid()){
delegate->downloadBufferMaximumSize = downloadBufferMaximumSizeAttribute.toLongLong();}else{// If there is no MaximumDownloadBufferSizeAttribute set (which is for the majority// of QNetworkRequest) then we can assume we'll do it anyway for small HTTP replies.// This helps with performance and memory fragmentation.
delegate->downloadBufferMaximumSize =128*1024;}// Connect the signals of the delegate to usQObject::connect(delegate,SIGNAL(downloadData(QByteArray)),
q,SLOT(replyDownloadData(QByteArray)),
Qt::QueuedConnection);QObject::connect(delegate,SIGNAL(downloadFinished()),
q,SLOT(replyFinished()),
Qt::QueuedConnection);
启动 -> finish 流程
voidQNetworkReplyHttpImplPrivate::replyFinished(){// We are already loading from cache, we still however// got this signal because it was posted alreadyif(loadingFromCache)return;finished();}
voidQNetworkReplyHttpImplPrivate::finished(){Q_Q(QNetworkReplyHttpImpl);if(state == Finished || state == Aborted || state == WaitingForSession)return;if(manager){}
state = Finished;
q->setFinished(true);
emit q->readChannelFinished();
emit q->finished();}