QAbstractSocket: try to send all data on flush()

Internal write buffer may have multiple blocks of data which wait a
transmission. In this case, ensuring a single write() is not enough to
flush the buffer completely. Allow several attempts that aim to write
as much as possible data from the buffer to the underlying network
socket.

Change-Id: I34b5ec65abe42853906168cdb05f793bd51162ec
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Alex Trotsenko 2015-09-07 16:54:59 +03:00
parent 25c0fdc885
commit aaab800e16
2 changed files with 26 additions and 10 deletions

View File

@ -816,8 +816,7 @@ bool QAbstractSocketPrivate::canWriteNotification()
#if defined (QABSTRACTSOCKET_DEBUG) #if defined (QABSTRACTSOCKET_DEBUG)
qDebug("QAbstractSocketPrivate::canWriteNotification() flushing"); qDebug("QAbstractSocketPrivate::canWriteNotification() flushing");
#endif #endif
qint64 tmp = writeBuffer.size(); bool dataWasWritten = writeToSocket();
flush();
if (socketEngine) { if (socketEngine) {
#if defined (Q_OS_WIN) #if defined (Q_OS_WIN)
@ -829,7 +828,7 @@ bool QAbstractSocketPrivate::canWriteNotification()
#endif #endif
} }
return (writeBuffer.size() < tmp); return dataWasWritten;
} }
/*! \internal /*! \internal
@ -851,21 +850,20 @@ void QAbstractSocketPrivate::connectionNotification()
/*! \internal /*! \internal
Writes pending data in the write buffers to the socket. The Writes one pending data block in the write buffer to the socket.
function writes as much as it can without blocking.
It is usually invoked by canWriteNotification after one or more It is usually invoked by canWriteNotification after one or more
calls to write(). calls to write().
Emits bytesWritten(). Emits bytesWritten().
*/ */
bool QAbstractSocketPrivate::flush() bool QAbstractSocketPrivate::writeToSocket()
{ {
Q_Q(QAbstractSocket); Q_Q(QAbstractSocket);
if (!socketEngine || !socketEngine->isValid() || (writeBuffer.isEmpty() if (!socketEngine || !socketEngine->isValid() || (writeBuffer.isEmpty()
&& socketEngine->bytesToWrite() == 0)) { && socketEngine->bytesToWrite() == 0)) {
#if defined (QABSTRACTSOCKET_DEBUG) #if defined (QABSTRACTSOCKET_DEBUG)
qDebug("QAbstractSocketPrivate::flush() nothing to do: valid ? %s, writeBuffer.isEmpty() ? %s", qDebug("QAbstractSocketPrivate::writeToSocket() nothing to do: valid ? %s, writeBuffer.isEmpty() ? %s",
(socketEngine && socketEngine->isValid()) ? "yes" : "no", writeBuffer.isEmpty() ? "yes" : "no"); (socketEngine && socketEngine->isValid()) ? "yes" : "no", writeBuffer.isEmpty() ? "yes" : "no");
#endif #endif
@ -885,7 +883,8 @@ bool QAbstractSocketPrivate::flush()
socketError = socketEngine->error(); socketError = socketEngine->error();
q->setErrorString(socketEngine->errorString()); q->setErrorString(socketEngine->errorString());
#if defined (QABSTRACTSOCKET_DEBUG) #if defined (QABSTRACTSOCKET_DEBUG)
qDebug() << "QAbstractSocketPrivate::flush() write error, aborting." << socketEngine->errorString(); qDebug() << "QAbstractSocketPrivate::writeToSocket() write error, aborting."
<< socketEngine->errorString();
#endif #endif
emit q->error(socketError); emit q->error(socketError);
// an unexpected error so close the socket. // an unexpected error so close the socket.
@ -894,7 +893,7 @@ bool QAbstractSocketPrivate::flush()
} }
#if defined (QABSTRACTSOCKET_DEBUG) #if defined (QABSTRACTSOCKET_DEBUG)
qDebug("QAbstractSocketPrivate::flush() %lld bytes written to the network", qDebug("QAbstractSocketPrivate::writeToSocket() %lld bytes written to the network",
written); written);
#endif #endif
@ -915,7 +914,23 @@ bool QAbstractSocketPrivate::flush()
if (state == QAbstractSocket::ClosingState) if (state == QAbstractSocket::ClosingState)
q->disconnectFromHost(); q->disconnectFromHost();
return true; return written > 0;
}
/*! \internal
Writes pending data in the write buffers to the socket. The function
writes as much as it can without blocking. If any data was written,
this function returns true; otherwise false is returned.
*/
bool QAbstractSocketPrivate::flush()
{
bool dataWasWritten = false;
while (!writeBuffer.isEmpty() && writeToSocket())
dataWasWritten = true;
return dataWasWritten;
} }
#ifndef QT_NO_NETWORKPROXY #ifndef QT_NO_NETWORKPROXY

View File

@ -135,6 +135,7 @@ public:
void fetchConnectionParameters(); void fetchConnectionParameters();
void setupSocketNotifiers(); void setupSocketNotifiers();
bool readFromSocket(); bool readFromSocket();
bool writeToSocket();
void emitReadyRead(); void emitReadyRead();
qint64 readBufferMaxSize; qint64 readBufferMaxSize;