diff options
author | Markus Goetz <Markus.Goetz@nokia.com> | 2009-07-22 07:59:54 (GMT) |
---|---|---|
committer | Markus Goetz <Markus.Goetz@nokia.com> | 2009-07-23 10:18:38 (GMT) |
commit | d6a01d0f948361ac5cacab0bf9f8585041485259 (patch) | |
tree | f17bc439920c2f366be9528cf41bc45e69209fc3 | |
parent | 9377881d6d6f5c07aa134c8f1708d0afd0d06e86 (diff) | |
download | Qt-d6a01d0f948361ac5cacab0bf9f8585041485259.zip Qt-d6a01d0f948361ac5cacab0bf9f8585041485259.tar.gz Qt-d6a01d0f948361ac5cacab0bf9f8585041485259.tar.bz2 |
Sockets: Added support for SO_KEEPALIVE and TCP_NODELAY
Introduce QAbstractSocket::setSocketOption that allows
to set the socket options for TCP Keep Alive and
TCP_NODELAY (disabling Nagle's Algorithm).
Reviewed-by: Thiago
-rw-r--r-- | src/network/socket/qabstractsocket.cpp | 64 | ||||
-rw-r--r-- | src/network/socket/qabstractsocket.h | 8 | ||||
-rw-r--r-- | src/network/socket/qabstractsocketengine_p.h | 4 | ||||
-rw-r--r-- | src/network/socket/qhttpsocketengine.cpp | 21 | ||||
-rw-r--r-- | src/network/socket/qnativesocketengine_unix.cpp | 24 | ||||
-rw-r--r-- | src/network/socket/qnativesocketengine_win.cpp | 22 | ||||
-rw-r--r-- | src/network/socket/qsocks5socketengine.cpp | 20 | ||||
-rw-r--r-- | src/network/socket/qtcpsocket.h | 1 |
8 files changed, 154 insertions, 10 deletions
diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp index d099382..be90b96 100644 --- a/src/network/socket/qabstractsocket.cpp +++ b/src/network/socket/qabstractsocket.cpp @@ -332,6 +332,22 @@ \sa QAbstractSocket::state() */ +/*! + \enum QAbstractSocket::SocketOption + \since 4.6 + + This enum represents the options that can be set on a socket. + If desired, they can be set after having received the connected() signal from + the socket or after having received a new socket from a QTcpServer. + + \value LowDelayOption Try to optimize the socket for low latency. For a QTcpSocket + this would set the TCP_NODELAY option and disable Nagle's algorithm. Set this to 1 + to enable. + \value KeepAliveOption Set this to 1 to enable the SO_KEEPALIVE socket option + + \sa QAbstractSocket::setSocketOption(), QAbstractSocket::socketOption() +*/ + #include "qabstractsocket.h" #include "qabstractsocket_p.h" @@ -1548,6 +1564,54 @@ bool QAbstractSocket::setSocketDescriptor(int socketDescriptor, SocketState sock return true; } +/*! + Sets the option \a option to the value described by \a value. + + \sa socketOption() +*/ +void QAbstractSocket::setSocketOption(QAbstractSocket::SocketOption option, QVariant value) +{ + if (!d_func()->socketEngine) + return; + + switch (option) { + case LowDelayOption: + d_func()->socketEngine->setOption(QAbstractSocketEngine::LowDelayOption, value.toInt()); + break; + + case KeepAliveOption: + d_func()->socketEngine->setOption(QAbstractSocketEngine::KeepAliveOption, value.toInt()); + break; + } +} + +/*! + Returns the value of the \a option option. + + \sa setSocketOption() +*/ +QVariant QAbstractSocket::socketOption(QAbstractSocket::SocketOption option) +{ + if (!d_func()->socketEngine) + return QVariant(); + + int ret = -1; + switch (option) { + case LowDelayOption: + ret = d_func()->socketEngine->option(QAbstractSocketEngine::LowDelayOption); + break; + + case KeepAliveOption: + ret = d_func()->socketEngine->option(QAbstractSocketEngine::KeepAliveOption); + break; + } + if (ret == -1) + return QVariant(); + else + return QVariant(ret); +} + + /* Returns the difference between msecs and elapsed. If msecs is -1, however, -1 is returned. diff --git a/src/network/socket/qabstractsocket.h b/src/network/socket/qabstractsocket.h index ed187e5..50a38bb 100644 --- a/src/network/socket/qabstractsocket.h +++ b/src/network/socket/qabstractsocket.h @@ -116,6 +116,10 @@ public: Connection = ConnectedState #endif }; + enum SocketOption { + LowDelayOption, // TCP_NODELAY + KeepAliveOption // SO_KEEPALIVE + }; QAbstractSocket(SocketType socketType, QObject *parent); virtual ~QAbstractSocket(); @@ -149,6 +153,10 @@ public: bool setSocketDescriptor(int socketDescriptor, SocketState state = ConnectedState, OpenMode openMode = ReadWrite); + // ### Qt 5: Make virtual? + void setSocketOption(QAbstractSocket::SocketOption o, QVariant v); + QVariant socketOption(QAbstractSocket::SocketOption o); + SocketType socketType() const; SocketState state() const; SocketError error() const; diff --git a/src/network/socket/qabstractsocketengine_p.h b/src/network/socket/qabstractsocketengine_p.h index b784f65..39c00cc 100644 --- a/src/network/socket/qabstractsocketengine_p.h +++ b/src/network/socket/qabstractsocketengine_p.h @@ -92,7 +92,9 @@ public: SendBufferSocketOption, AddressReusable, BindExclusively, - ReceiveOutOfBandData + ReceiveOutOfBandData, + LowDelayOption, + KeepAliveOption }; virtual bool initialize(QAbstractSocket::SocketType type, QAbstractSocket::NetworkLayerProtocol protocol = QAbstractSocket::IPv4Protocol) = 0; diff --git a/src/network/socket/qhttpsocketengine.cpp b/src/network/socket/qhttpsocketengine.cpp index 156a9f4..84b7c14 100644 --- a/src/network/socket/qhttpsocketengine.cpp +++ b/src/network/socket/qhttpsocketengine.cpp @@ -276,13 +276,30 @@ qint64 QHttpSocketEngine::pendingDatagramSize() const } #endif // QT_NO_UDPSOCKET -int QHttpSocketEngine::option(SocketOption) const +int QHttpSocketEngine::option(SocketOption option) const { + Q_D(const QHttpSocketEngine); + if (d->socket) { + // convert the enum and call the real socket + if (option == QAbstractSocketEngine::LowDelayOption) + return d->socket->socketOption(QAbstractSocket::LowDelayOption).toInt(); + if (option == QAbstractSocketEngine::KeepAliveOption) + return d->socket->socketOption(QAbstractSocket::KeepAliveOption).toInt(); + } return -1; } -bool QHttpSocketEngine::setOption(SocketOption, int) +bool QHttpSocketEngine::setOption(SocketOption option, int value) { + Q_D(QHttpSocketEngine); + if (d->socket) { + // convert the enum and call the real socket + if (option == QAbstractSocketEngine::LowDelayOption) + d->socket->setSocketOption(QAbstractSocket::LowDelayOption, value); + if (option == QAbstractSocketEngine::KeepAliveOption) + d->socket->setSocketOption(QAbstractSocket::KeepAliveOption, value); + return true; + } return false; } diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp index 3991ae6..b4b673a 100644 --- a/src/network/socket/qnativesocketengine_unix.cpp +++ b/src/network/socket/qnativesocketengine_unix.cpp @@ -65,6 +65,8 @@ #include <ctype.h> #endif +#include <netinet/tcp.h> + QT_BEGIN_NAMESPACE #if defined QNATIVESOCKETENGINE_DEBUG @@ -203,6 +205,8 @@ int QNativeSocketEnginePrivate::option(QNativeSocketEngine::SocketOption opt) co return -1; int n = -1; + int level = SOL_SOCKET; // default + switch (opt) { case QNativeSocketEngine::ReceiveBufferSocketOption: n = SO_RCVBUF; @@ -222,11 +226,18 @@ int QNativeSocketEnginePrivate::option(QNativeSocketEngine::SocketOption opt) co case QNativeSocketEngine::ReceiveOutOfBandData: n = SO_OOBINLINE; break; + case QNativeSocketEngine::LowDelayOption: + level = IPPROTO_TCP; + n = TCP_NODELAY; + break; + case QNativeSocketEngine::KeepAliveOption: + n = SO_KEEPALIVE; + break; } int v = -1; QT_SOCKOPTLEN_T len = sizeof(v); - if (getsockopt(socketDescriptor, SOL_SOCKET, n, (char *) &v, &len) != -1) + if (getsockopt(socketDescriptor, level, n, (char *) &v, &len) != -1) return v; return -1; } @@ -242,6 +253,8 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt return false; int n = 0; + int level = SOL_SOCKET; // default + switch (opt) { case QNativeSocketEngine::ReceiveBufferSocketOption: n = SO_RCVBUF; @@ -282,9 +295,16 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt case QNativeSocketEngine::ReceiveOutOfBandData: n = SO_OOBINLINE; break; + case QNativeSocketEngine::LowDelayOption: + level = IPPROTO_TCP; + n = TCP_NODELAY; + break; + case QNativeSocketEngine::KeepAliveOption: + n = SO_KEEPALIVE; + break; } - return ::setsockopt(socketDescriptor, SOL_SOCKET, n, (char *) &v, sizeof(v)) == 0; + return ::setsockopt(socketDescriptor, level, n, (char *) &v, sizeof(v)) == 0; } bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16 port) diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp index 6bc23ce..f0b9f0b 100644 --- a/src/network/socket/qnativesocketengine_win.cpp +++ b/src/network/socket/qnativesocketengine_win.cpp @@ -362,6 +362,8 @@ int QNativeSocketEnginePrivate::option(QNativeSocketEngine::SocketOption opt) co return -1; int n = -1; + int level = SOL_SOCKET; // default + switch (opt) { case QNativeSocketEngine::ReceiveBufferSocketOption: n = SO_RCVBUF; @@ -389,11 +391,18 @@ int QNativeSocketEnginePrivate::option(QNativeSocketEngine::SocketOption opt) co case QNativeSocketEngine::ReceiveOutOfBandData: n = SO_OOBINLINE; break; + case QNativeSocketEngine::LowDelayOption: + level = IPPROTO_TCP; + n = TCP_NODELAY; + break; + case QNativeSocketEngine::KeepAliveOption: + n = SO_KEEPALIVE; + break; } int v = -1; QT_SOCKOPTLEN_T len = sizeof(v); - if (getsockopt(socketDescriptor, SOL_SOCKET, n, (char *) &v, &len) != -1) + if (getsockopt(socketDescriptor, level, n, (char *) &v, &len) != -1) return v; return -1; } @@ -409,6 +418,8 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt return false; int n = 0; + int level = SOL_SOCKET; // default + switch (opt) { case QNativeSocketEngine::ReceiveBufferSocketOption: n = SO_RCVBUF; @@ -440,9 +451,16 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt case QNativeSocketEngine::ReceiveOutOfBandData: n = SO_OOBINLINE; break; + case QNativeSocketEngine::LowDelayOption: + level = IPPROTO_TCP; + n = TCP_NODELAY; + break; + case QNativeSocketEngine::KeepAliveOption: + n = SO_KEEPALIVE; + break; } - if (::setsockopt(socketDescriptor, SOL_SOCKET, n, (char*)&v, sizeof(v)) != 0) { + if (::setsockopt(socketDescriptor, level, n, (char*)&v, sizeof(v)) != 0) { WS_ERROR_DEBUG(WSAGetLastError()); return false; } diff --git a/src/network/socket/qsocks5socketengine.cpp b/src/network/socket/qsocks5socketengine.cpp index c9e5150..d226f21 100644 --- a/src/network/socket/qsocks5socketengine.cpp +++ b/src/network/socket/qsocks5socketengine.cpp @@ -1621,14 +1621,28 @@ qint64 QSocks5SocketEngine::pendingDatagramSize() const int QSocks5SocketEngine::option(SocketOption option) const { - Q_UNUSED(option); + Q_D(const QSocks5SocketEngine); + if (d->data && d->data->controlSocket) { + // convert the enum and call the real socket + if (option == QAbstractSocketEngine::LowDelayOption) + return d->data->controlSocket->socketOption(QAbstractSocket::LowDelayOption).toInt(); + if (option == QAbstractSocketEngine::KeepAliveOption) + return d->data->controlSocket->socketOption(QAbstractSocket::KeepAliveOption).toInt(); + } return -1; } bool QSocks5SocketEngine::setOption(SocketOption option, int value) { - Q_UNUSED(option); - Q_UNUSED(value); + Q_D(QSocks5SocketEngine); + if (d->data && d->data->controlSocket) { + // convert the enum and call the real socket + if (option == QAbstractSocketEngine::LowDelayOption) + d->data->controlSocket->setSocketOption(QAbstractSocket::LowDelayOption, value); + if (option == QAbstractSocketEngine::KeepAliveOption) + d->data->controlSocket->setSocketOption(QAbstractSocket::KeepAliveOption, value); + return true; + } return false; } diff --git a/src/network/socket/qtcpsocket.h b/src/network/socket/qtcpsocket.h index 81f81de..4e1003a 100644 --- a/src/network/socket/qtcpsocket.h +++ b/src/network/socket/qtcpsocket.h @@ -43,6 +43,7 @@ #define QTCPSOCKET_H #include <QtNetwork/qabstractsocket.h> +#include <QtCore/qvariant.h> QT_BEGIN_HEADER |