📄 qabstractsocket.cpp
字号:
isBuffered(false), blockingTimeout(30000), connectTimer(0), connectTimeElapsed(0), hostLookupId(-1), state(QAbstractSocket::UnconnectedState), socketError(QAbstractSocket::UnknownSocketError)#ifndef QT_NO_NETWORKPROXY , proxy(0)#endif{}/*! \internal Destructs the QAbstractSocket. If the socket layer is open, it will be reset.*/QAbstractSocketPrivate::~QAbstractSocketPrivate(){#ifndef QT_NO_NETWORKPROXY delete proxy;#endif}/*! \internal Resets the socket layer, clears the read and write buffers and deletes any socket notifiers.*/void QAbstractSocketPrivate::resetSocketLayer(){#if defined (QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocketPrivate::resetSocketLayer()");#endif if (socketEngine) { socketEngine->close(); socketEngine->disconnect(); delete socketEngine; socketEngine = 0; cachedSocketDescriptor = -1; } if (connectTimer) { connectTimer->stop(); delete connectTimer; connectTimer = 0; }}/*! \internal Initializes the socket layer to by of type \a type, using the network layer protocol \a protocol. Resets the socket layer first if it's already initialized. Sets up the socket notifiers.*/bool QAbstractSocketPrivate::initSocketLayer(const QHostAddress &host, QAbstractSocket::SocketType type){ Q_Q(QAbstractSocket);#if defined (QABSTRACTSOCKET_DEBUG) QString typeStr; if (type == QAbstractSocket::TcpSocket) typeStr = "TcpSocket"; else if (type == QAbstractSocket::UdpSocket) typeStr = "UdpSocket"; else typeStr = "UnknownSocketType"; QString protocolStr; if (host.protocol() == QAbstractSocket::IPv4Protocol) protocolStr = "IPv4Protocol"; else if (host.protocol() == QAbstractSocket::IPv6Protocol) protocolStr = "IPv6Protocol"; else protocolStr = "UnknownNetworkLayerProtocol";#endif resetSocketLayer(); socketEngine = QAbstractSocketEngine::createSocketEngine(host, type, q); if (!socketEngine->initialize(type, host.protocol())) {#if defined (QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocketPrivate::initSocketLayer(%s, %s) failed (%s)", typeStr.toLatin1().constData(), protocolStr.toLatin1().constData(), socketEngine->errorString().toLatin1().constData());#endif socketError = socketEngine->error(); q->setErrorString(socketEngine->errorString()); return false; } cachedSocketDescriptor = socketEngine->socketDescriptor(); if (threadData->eventDispatcher) socketEngine->setReceiver(this);#if defined (QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocketPrivate::initSocketLayer(%s, %s) success", typeStr.toLatin1().constData(), protocolStr.toLatin1().constData());#endif return true;}/*! \internal Slot connected to the read socket notifier. This slot is called when new data is available for reading, or when the socket has been closed. Handles recursive calls.*/bool QAbstractSocketPrivate::canReadNotification(){ Q_Q(QAbstractSocket);#if defined (QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocketPrivate::canReadNotification()");#endif // Prevent recursive calls if (readSocketNotifierCalled) { if (!readSocketNotifierStateSet) { readSocketNotifierStateSet = true; readSocketNotifierState = socketEngine->isReadNotificationEnabled(); socketEngine->setReadNotificationEnabled(false); } } readSocketNotifierCalled = true; if (!isBuffered) socketEngine->setReadNotificationEnabled(false); // If buffered, read data from the socket into the read buffer qint64 newBytes = 0; if (isBuffered) { // Return if there is no space in the buffer if (readBufferMaxSize && readBuffer.size() >= readBufferMaxSize) {#if defined (QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocketPrivate::canReadNotification() buffer is full");#endif readSocketNotifierCalled = false; return false; } // If reading from the socket fails after getting a read // notification, close the socket. newBytes = readBuffer.size(); if (!readFromSocket()) {#if defined (QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocketPrivate::canReadNotification() disconnecting socket");#endif q->disconnectFromHost(); readSocketNotifierCalled = false; return false; } newBytes = readBuffer.size() - newBytes; // If read buffer is full, disable the read socket notifier. if (readBufferMaxSize && readBuffer.size() == readBufferMaxSize) { socketEngine->setReadNotificationEnabled(false); } } // only emit readyRead() when not recursing, and only if there is data available bool hasData = newBytes > 0#ifndef QT_NO_UDPSOCKET || (!isBuffered && socketEngine && socketEngine->hasPendingDatagrams())#endif ; if (!emittedReadyRead && hasData) { emittedReadyRead = true; emit q->readyRead(); emittedReadyRead = false; } // If we were closed as a result of the readyRead() signal, // return. if (state == QAbstractSocket::UnconnectedState || state == QAbstractSocket::ClosingState) {#if defined (QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocketPrivate::canReadNotification() socket is closing - returning");#endif readSocketNotifierCalled = false; return true; } if (!hasData && socketEngine) socketEngine->setReadNotificationEnabled(true); // reset the read socket notifier state if we reentered inside the // readyRead() connected slot. if (readSocketNotifierStateSet && socketEngine && readSocketNotifierState != socketEngine->isReadNotificationEnabled()) { socketEngine->setReadNotificationEnabled(readSocketNotifierState); readSocketNotifierStateSet = false; } readSocketNotifierCalled = false; return true;}/*! \internal Slot connected to the write socket notifier. It's called during a delayed connect or when the socket is ready for writing.*/bool QAbstractSocketPrivate::canWriteNotification(){#if defined (Q_OS_WIN) if (socketEngine && socketEngine->isWriteNotificationEnabled()) socketEngine->setWriteNotificationEnabled(false);#endif // If in connecting state, check if the connection has been // established, otherwise flush pending data. if (state == QAbstractSocket::ConnectingState) {#if defined (QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocketPrivate::canWriteNotification() testing connection");#endif _q_testConnection(); return false; }#if defined (QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocketPrivate::canWriteNotification() flushing");#endif int tmp = writeBuffer.size(); flush(); if (socketEngine) {#if defined (Q_OS_WIN) if (!writeBuffer.isEmpty()) socketEngine->setWriteNotificationEnabled(true);#else if (writeBuffer.isEmpty()) socketEngine->setWriteNotificationEnabled(false);#endif } return (writeBuffer.size() < tmp);}/*! \internal Writes pending data in the write buffers to the socket. The function writes as much as it can without blocking. It is usually invoked by canWriteNotification after one or more calls to write(). Emits bytesWritten().*/bool QAbstractSocketPrivate::flush(){ Q_Q(QAbstractSocket); if (!socketEngine || !socketEngine->isValid() || writeBuffer.isEmpty()) {#if defined (QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocketPrivate::flush() nothing to do: valid ? %s, writeBuffer.isEmpty() ? %s", socketEngine->isValid() ? "yes" : "no", writeBuffer.isEmpty() ? "yes" : "no");#endif return false; } int nextSize = writeBuffer.nextDataBlockSize(); const char *ptr = writeBuffer.readPointer(); // Attempt to write it all in one chunk. qint64 written = socketEngine->write(ptr, nextSize); if (written < 0) { socketError = socketEngine->error(); q->setErrorString(socketEngine->errorString()); emit q->error(socketError); // an unexpected error so close the socket.#if defined (QABSTRACTSOCKET_DEBUG) qDebug() << "QAbstractSocketPrivate::flush() write error, aborting." << socketEngine->errorString();#endif q->abort(); return false; }#if defined (QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocketPrivate::flush() %lld bytes written to the network", written);#endif // Remove what we wrote so far. writeBuffer.free(written); if (written > 0) { // Don't emit bytesWritten() recursively. if (!emittedBytesWritten) { emittedBytesWritten = true; emit q->bytesWritten(written); emittedBytesWritten = false; } } if (writeBuffer.isEmpty() && socketEngine && socketEngine->isWriteNotificationEnabled()) socketEngine->setWriteNotificationEnabled(false); if (state == QAbstractSocket::ClosingState) q->close(); return true;}/*! \internal Slot connected to QHostInfo::lookupHost() in connectToHost(). This function starts the process of connecting to any number of candidate IP addresses for the host, if it was found. Calls _q_connectToNextAddress().*/void QAbstractSocketPrivate::_q_startConnecting(const QHostInfo &hostInfo){ Q_Q(QAbstractSocket); if (state == QAbstractSocket::ConnectingState || state == QAbstractSocket::ConnectedState) return; addresses = hostInfo.addresses();#if defined(QABSTRACTSOCKET_DEBUG) QString s = "{"; for (int i = 0; i < addresses.count(); ++i) { if (i != 0) s += ", "; s += addresses.at(i).toString(); } s += "}"; qDebug("QAbstractSocketPrivate::_q_startConnecting(hostInfo == %s)", s.toLatin1().constData());#endif // Try all addresses twice. addresses += addresses; // If there are no addresses in the host list, report this to the // user. if (addresses.isEmpty()) {#if defined(QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocketPrivate::_q_startConnecting(), host not found");#endif state = QAbstractSocket::UnconnectedState; socketError = QAbstractSocket::HostNotFoundError; q->setErrorString(QLatin1String(QT_TRANSLATE_NOOP("QAbstractSocket", "Host not found"))); emit q->stateChanged(state); emit q->error(QAbstractSocket::HostNotFoundError); return; } // Enter Connecting state (see also sn_write, which is called by // the write socket notifier after connect()) state = QAbstractSocket::ConnectingState; emit q->stateChanged(state); // Report the successful host lookup emit q->hostFound(); // Reset the total time spent connecting. connectTimeElapsed = 0; // The addresses returned by the lookup will be tested one after // another by _q_connectToNextAddress(). _q_connectToNextAddress();}/*! \internal Called by a queued or direct connection from _q_startConnecting() or _q_testConnection(), this function takes the first address of the pending addresses list and tries to connect to it. If the connection succeeds, QAbstractSocket will emit connected(). Otherwise, error(ConnectionRefusedError) or error(SocketTimeoutError) is emitted.*/void QAbstractSocketPrivate::_q_connectToNextAddress(){ Q_Q(QAbstractSocket); do { // Check for more pending addresses if (addresses.isEmpty()) {#if defined(QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocketPrivate::_q_connectToNextAddress(), all addresses failed.");#endif state = QAbstractSocket::UnconnectedState; if (socketEngine) { if ((socketEngine->error() == QAbstractSocket::UnknownSocketError#ifdef Q_OS_AIX // On AIX, the second connect call will result in EINVAL and not // ECONNECTIONREFUSED; although the meaning is the same. || socketEngine->error() == QAbstractSocket::UnsupportedSocketOperationError#endif ) && socketEngine->state() == QAbstractSocket::ConnectingState) { socketError = QAbstractSocket::ConnectionRefusedError; q->setErrorString(QLatin1String(QT_TRANSLATE_NOOP("QAbstractSocket", "Connection refused"))); } else { socketError = socketEngine->error(); q->setErrorString(socketEngine->errorString()); } } else { socketError = QAbstractSocket::ConnectionRefusedError; q->setErrorString(QLatin1String(QT_TRANSLATE_NOOP("QAbstractSocket", "Connection refused"))); } emit q->stateChanged(state); emit q->error(socketError); return; } // Pick the first host address candidate host = addresses.takeFirst();#if defined(QABSTRACTSOCKET_DEBUG)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -