📄 qabstractsocket.cpp
字号:
qDebug("QAbstractSocketPrivate::_q_connectToNextAddress(), connecting to %s:%i", host.toString().toLatin1().constData(), port);#endif#if defined(QT_NO_IPV6) if (host.protocol() == QAbstractSocket::IPv6Protocol) { // If we have no IPv6 support, then we will not be able to // connect. So we just pretend we didn't see this address.#if defined(QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocketPrivate::_q_connectToNextAddress(), skipping IPv6 entry");#endif continue; }#endif if (!initSocketLayer(host, q->socketType())) { // hope that the next address is better#if defined(QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocketPrivate::_q_connectToNextAddress(), failed to initialize sock layer");#endif continue; } // Tries to connect to the address. If it succeeds immediately // (localhost address on BSD or any UDP connect), emit // connected() and return. if (socketEngine->connectToHost(host, port)) { fetchConnectionParameters(); return; } // Check that we're in delayed connection state. If not, try // the next address if (socketEngine->state() != QAbstractSocket::ConnectingState) {#if defined(QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocketPrivate::_q_connectToNextAddress(), connection failed (%s)", socketEngine->errorString().toLatin1().constData());#endif continue; } // Start the connect timer. if (threadData->eventDispatcher) { if (!connectTimer) { connectTimer = new QTimer(q); QObject::connect(connectTimer, SIGNAL(timeout()), q, SLOT(_q_abortConnectionAttempt())); } connectTimer->start(QT_CONNECT_TIMEOUT); } // Wait for a write notification that will eventually call // _q_testConnection(). socketEngine->setWriteNotificationEnabled(true); break; } while (state != QAbstractSocket::ConnectedState);}/*! \internal Tests if a connection has been established. If it has, connected() is emitted. Otherwise, _q_connectToNextAddress() is invoked.*/void QAbstractSocketPrivate::_q_testConnection(){ if (socketEngine) { if (socketEngine->state() != QAbstractSocket::ConnectedState) { // Try connecting if we're not already connected. if (!socketEngine->connectToHost(host, port)) { if (socketEngine->error() == QAbstractSocket::UnfinishedSocketOperationError) { // Connection in progress; wait for the next notification. socketEngine->setWriteNotificationEnabled(true); return; } } } if (threadData->eventDispatcher) { if (connectTimer) connectTimer->stop(); } if (socketEngine->state() == QAbstractSocket::ConnectedState) { // Fetch the parameters if our connection is completed; // otherwise, fall out and try the next address. fetchConnectionParameters(); return; } // don't retry the other addresses if we couldn't authenticate to the proxy. if (socketEngine->error() == QAbstractSocket::ProxyAuthenticationRequiredError) addresses.clear(); } if (threadData->eventDispatcher) { if (connectTimer) connectTimer->stop(); }#if defined(QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocketPrivate::_q_testConnection() connection failed," " checking for alternative addresses");#endif _q_connectToNextAddress();}/*! \internal This function is called after a certain number of seconds has passed while waiting for a connection. It simply tests the connection, and continues to the next address if the connection failed.*/void QAbstractSocketPrivate::_q_abortConnectionAttempt(){#if defined(QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocketPrivate::_q_abortConnectionAttempt() (timed out)");#endif if (socketEngine) { socketEngine->setWriteNotificationEnabled(false); if (socketEngine->isValid()) _q_testConnection(); }}/*! \internal Reads data from the socket layer into the read buffer. Returns true on success; otherwise false.*/bool QAbstractSocketPrivate::readFromSocket(){ Q_Q(QAbstractSocket); // Find how many bytes we can read from the socket layer. qint64 bytesToRead = socketEngine->bytesAvailable();#ifdef Q_OS_LINUX if (bytesToRead > 0) // ### See setSocketDescriptor() bytesToRead += addToBytesAvailable;#endif if (bytesToRead == 0) { // Under heavy load, certain conditions can trigger read notifications // for socket notifiers on which there is no activity. If we continue // to read 0 bytes from the socket, we will trigger behavior similar // to that which signals a remote close. When we hit this condition, // we try to read 4k of data from the socket, which will give us either // an EAGAIN/EWOULDBLOCK if the connection is alive (i.e., the remote // host has _not_ disappeared). bytesToRead = 4096; } if (readBufferMaxSize && bytesToRead > (readBufferMaxSize - readBuffer.size())) bytesToRead = readBufferMaxSize - readBuffer.size();#if defined(QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocketPrivate::readFromSocket() about to read %d bytes", int(bytesToRead));#endif // Read from the socket, store data in the read buffer. char *ptr = readBuffer.reserve(bytesToRead); qint64 readBytes = socketEngine->read(ptr, bytesToRead); if (readBytes == -2) { // No bytes currently available for reading. readBuffer.chop(bytesToRead); return true; } readBuffer.chop(int(bytesToRead - (readBytes < 0 ? qint64(0) : readBytes)));#if defined(QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocketPrivate::readFromSocket() got %d bytes, buffer size = %d", int(readBytes), readBuffer.size());#endif if (!socketEngine->isValid()) { socketError = socketEngine->error(); q->setErrorString(socketEngine->errorString()); emit q->error(socketError);#if defined(QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocketPrivate::readFromSocket() read failed: %s", q->errorString().toLatin1().constData());#endif resetSocketLayer(); return false; } return true;}/*! \internal Sets up the the internal state after the connection has succeeded.*/void QAbstractSocketPrivate::fetchConnectionParameters(){ Q_Q(QAbstractSocket); peerName = hostName; if (socketEngine) { socketEngine->setReadNotificationEnabled(true); socketEngine->setWriteNotificationEnabled(true); localPort = socketEngine->localPort(); peerPort = socketEngine->peerPort(); localAddress = socketEngine->localAddress(); peerAddress = socketEngine->peerAddress(); cachedSocketDescriptor = socketEngine->socketDescriptor(); } state = QAbstractSocket::ConnectedState; emit q->stateChanged(state); emit q->connected();#if defined(QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocketPrivate::fetchConnectionParameters() connection to %s:%i established", host.toString().toLatin1().constData(), port);#endif}/*! \internal Constructs a new abstract socket of type \a socketType. The \a parent argument is passed to QObject's constructor.*/QAbstractSocket::QAbstractSocket(SocketType socketType, QAbstractSocketPrivate &dd, QObject *parent) : QIODevice(dd, parent){ Q_D(QAbstractSocket);#if defined(QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocket::QAbstractSocket(%sSocket, QAbstractSocketPrivate == %p, parent == %p)", socketType == TcpSocket ? "Tcp" : socketType == UdpSocket ? "Udp" : "Unknown", &dd, parent);#endif d->socketType = socketType;}/*! Creates a new abstract socket of type \a socketType. The \a parent argument is passed to QObject's constructor. \sa socketType(), QTcpSocket, QUdpSocket*/QAbstractSocket::QAbstractSocket(SocketType socketType, QObject *parent) : QIODevice(*new QAbstractSocketPrivate, parent){ Q_D(QAbstractSocket);#if defined(QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocket::QAbstractSocket(%p)", parent);#endif d->socketType = socketType;}/*! Destroys the socket.*/QAbstractSocket::~QAbstractSocket(){ Q_D(QAbstractSocket);#if defined(QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocket::~QAbstractSocket()");#endif if (d->state != UnconnectedState) abort();}/*! Returns true if the socket is valid and ready for use; otherwise returns false. \bold{Note:} The socket's state must be ConnectedState before reading and writing can occur. \sa state()*/bool QAbstractSocket::isValid() const{ return d_func()->socketEngine ? d_func()->socketEngine->isValid() : isOpen();}/*! Attempts to make a connection to \a hostName on the given \a port. The socket is opened in the given \a openMode and first enters HostLookupState, then performs a host name lookup of \a hostName. If the lookup succeeds, hostFound() is emitted and QAbstractSocket enters ConnectingState. It then attempts to connect to the address or addresses returned by the lookup. Finally, if a connection is established, QAbstractSocket enters ConnectedState and emits connected(). At any point, the socket can emit error() to signal that an error occurred. \a hostName may be an IP address in string form (e.g., "43.195.83.32"), or it may be a host name (e.g., "www.trolltech.com"). QAbstractSocket will do a lookup only if required. \a port is in native byte order. \sa state(), peerName(), peerAddress(), peerPort(), waitForConnected()*/void QAbstractSocket::connectToHost(const QString &hostName, quint16 port, OpenMode openMode){ QMetaObject::invokeMethod(this, "connectToHostImplementation", Q_ARG(QString, hostName), Q_ARG(quint16, port), Q_ARG(OpenMode, openMode));}/*! \since 4.1 Contains the implementation of connectToHost(). Attempts to make a connection to \a hostName on the given \a port. The socket is opened in the given \a openMode.*/void QAbstractSocket::connectToHostImplementation(const QString &hostName, quint16 port, OpenMode openMode){ Q_D(QAbstractSocket);#if defined(QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocket::connectToHost(\"%s\", %i, %i)...", hostName.toLatin1().constData(), port, (int) openMode);#endif if (d->state == ConnectedState || d->state == ConnectingState) { qWarning("QAbstractSocket::connectToHost() called when already connecting/connected"); return; } d->hostName = hostName; d->port = port; d->state = HostLookupState; d->readBuffer.clear(); d->writeBuffer.clear(); d->closeCalled = false; d->localPort = 0; d->peerPort = 0; d->localAddress.clear(); d->peerAddress.clear(); d->peerName = hostName;#ifdef Q_OS_LINUX // ### See setSocketDescriptor(). d->addToBytesAvailable = 0;#endif if (d->hostLookupId != -1) { QHostInfo::abortHostLookup(d->hostLookupId); d->hostLookupId = -1; } if (!d_func()->isBuffered) openMode |= QAbstractSocket::Unbuffered; setOpenMode(openMode); emit stateChanged(d->state); QHostAddress temp; if (temp.setAddress(hostName)) { QHostInfo info; info.setAddresses(QList<QHostAddress>() << temp); d->_q_startConnecting(info); } else { if (d->threadData->eventDispatcher) d->hostLookupId = QHostInfo::lookupHost(hostName, this, SLOT(_q_startConnecting(QHostInfo))); }#if defined(QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocket::connectToHost(\"%s\", %i) == %s%s", hostName.toLatin1().constData(), port, (d->state == ConnectedState) ? "true" : "false", (d->state == ConnectingState || d->state == HostLookupState) ? " (connection in progress)" : "");#endif}/*! \overload Attempts to make a connection to \a address on port \a port.*/void QAbstractSocket::connectToHost(const QHostAddress &address, quint16 port, OpenMode openMode){#if defined(QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocket::connectToHost([%s], %i, %i)...", address.toString().toLatin1().constData(), port, (int) openMode);#endif connectToHost(address.toString(), port, openMode);}/*! Returns the number of bytes that are waiting to be written. The bytes are written when control goes back to the event loop or when flush() is called. \sa bytesAvailable(), flush()*/qint64 QAbstractSocket::bytesToWrite() const{ Q_D(const QAbstractSocket);#if defined(QABSTRACTSOCKET_DEBUG)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -