Socket Engine
Using English to describe my idea is so hard for me, but I should take the bull by horns. I know that English will be accompanied by my life. So I must work hard to make it better. Are you in the same page with me? If you agree with me, here we go.
The creative spirit is so important in our daily life, so we need try to think out of the box everywhere.
Now let’s come to today’s analyze of socket engine.
First, let’s find where the object of QAbstractSocketEngine is created.
In the QTcpServerPrivate class, I find the pointer of QAbstractSocketEngine class. So let’s come to the constructor of QAbstractSocketEngine.
QTcpServerPrivate::QTcpServerPrivate()
: port(0)
, state(QAbstractSocket::UnconnectedState)
, socketEngine(0)
, serverSocketError(QAbstractSocket::UnknownSocketError)
, maxConnections(30)
{
}
The only thing is to set the socket engine pointer to NULL.
In the listen () function, they call the createSocketEngine () function.
d->socketEngine = QAbstractSocketEngine::createSocketEngine(QAbstractSocket::TcpSocket, proxy, this);
Here is the realization of createSocketEngine.
QAbstractSocketEngine *QAbstractSocketEngine::createSocketEngine(QAbstractSocket::SocketType socketType, const QNetworkProxy &proxy, QObject *parent)
{
#ifndef QT_NO_NETWORKPROXY
// proxy type must have been resolved by now
if (proxy.type() == QNetworkProxy::DefaultProxy)
return 0;
#endif
QMutexLocker locker(&socketHandlers()->mutex);
for (int i = 0; i < socketHandlers()->size(); i++) {
if (QAbstractSocketEngine *ret = socketHandlers()->at(i)->createSocketEngine(socketType, proxy, parent))
return ret;
}
#ifndef QT_NO_NETWORKPROXY
// only NoProxy can have reached here
if (proxy.type() != QNetworkProxy::NoProxy)
return 0;
#endif
return new QNativeSocketEngine(parent);
}
Here we can see the QNativeSocketEngine object was created.
In the constructor of QNativeSocketEngine class, the object of QNativeSocketEnginePrivate was created.
QNativeSocketEngine::QNativeSocketEngine(QObject *parent)
: QAbstractSocketEngine(*new QNativeSocketEnginePrivate(), parent)
{
}
QNativeSocketEnginePrivate::QNativeSocketEnginePrivate()
{
socketDescriptor = -1;
readNotifier = 0;
writeNotifier = 0;
exceptNotifier = 0;
}
After the object was created, the initialize () function was called.
if (!d->socketEngine->initialize(QAbstractSocket::TcpSocket, proto)) {
d->serverSocketError = d->socketEngine->error();
d->serverSocketErrorString = d->socketEngine->errorString();
return false;
}
The description of initialize () function.
/*!
Initializes a QNativeSocketEngine by creating a new socket of type /a
socketType and network layer protocol /a protocol. Returns true on
success; otherwise returns false.
If the socket was already initialized, this function closes the
socket before reeinitializing it.
The new socket is non-blocking, and for UDP sockets it's also
broadcast enabled.
*/
First, they create the new socket by call the createNewSocket () function from QNativeSocketEnginePrivate class.
Then, here is something we need attention on Qt4.6.0.
// Before Qt 4.6, we always set the send and receive buffer size to 49152 as
// this was found to be an optimal value. However, modern OS
// all have some kind of auto tuning for this and we therefore don't set
// this explictly anymore.
// If it introduces any performance regressions for Qt 4.6.x (x > 0) then
// it will be put back in.
//
// You can use tests/manual/qhttpnetworkconnection to test HTTP download speed
// with this.
//
// pre-4.6:
// setReceiveBufferSize(49152);
// setSendBufferSize(49152);
End of this function, they save the socket information.
d->socketType = socketType;
d->socketProtocol = protocol;
Then the bind () function was called. In this function, nativeBind () function was called.
if (!d->nativeBind(address, port))
return false;
The nativeBind () function is an platform-specific function. Let’s look the version of windows.
In the qnativesocketengine_win.cpp, I have seen the createNewSocket () function. Create a windows socket by call this.
SOCKET socket = ::WSASocket(protocol, type, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
Here is the realization by using win32 API function.
qt_socket_setPortAndAddress(socketDescriptor, &sockAddrIPv4, &sockAddrIPv6, port, address, &sockAddrPtr, &sockAddrSize);
int bindResult = ::bind(socketDescriptor, sockAddrPtr, sockAddrSize);
And the nativeListen () function is on the same page.
if (::listen(socketDescriptor, backlog) == SOCKET_ERROR)
Here is all the analyzing today. Next day, I will continue this part.
November 16, 2009 23:20