I'm trying to make IPC work between one server to accept requests from multiple clients with Qt 4.6. All is working, except that the underlying named pipes are not being closed, making Qt to emit the maximum handle reached message (62).
Since I want to accept several client connections, I handle newConnections to the QLocalServer class as follows:
void ServerImpl::onNewConnection()
{
QLocalSocket * plsocket = _server->nextPendingConnection();
SocketHandler* skh = new SocketHandler(plsocket, this, this);
connect(plsocket, SIGNAL(readyRead()), skh, SLOT(socketReadyRead()));
connect(plsocket, SIGNAL(error(QLocalSocket::LocalSocketError)), skh,
SLOT(onError(QLocalSocket::LocalSocketError)));
connect(plsocket, SIGNAL(disconnected()), skh, SLOT(disconnected()));
}
void ServerImpl::onNewConnection()
{
QLocalSocket * plsocket = _server->nextPendingConnection();
SocketHandler* skh = new SocketHandler(plsocket, this, this);
connect(plsocket, SIGNAL(readyRead()), skh, SLOT(socketReadyRead()));
connect(plsocket, SIGNAL(error(QLocalSocket::LocalSocketError)), skh,
SLOT(onError(QLocalSocket::LocalSocketError)));
connect(plsocket, SIGNAL(disconnected()), skh, SLOT(disconnected()));
}
To copy to clipboard, switch view to plain text mode
Since every time I get a new connection the QLocalSocket pointer received from QLocalServer::nextPendingConnection() is overwritten, I manage the data requests through the SocketHandler class, which of course encapsulates a QLocalSocket class:
void SocketHandler::socketReadyRead()
{
forever
{
if (_blocksize == 0)
{
if (_ps->bytesAvailable() < sizeof(blocksize_t))
return;
in >> _blocksize;
}
// We need more data?
if (_ps->bytesAvailable() < _blocksize)
return;
_srv->ReadRequest(in);
// CHECK: Discard remaining blocks
_blocksize = 0;
}
}
void SocketHandler::socketReadyRead()
{
QDataStream in(_ps);
in.setVersion(QDataStream::Qt_4_5);
forever
{
if (_blocksize == 0)
{
if (_ps->bytesAvailable() < sizeof(blocksize_t))
return;
in >> _blocksize;
}
// We need more data?
if (_ps->bytesAvailable() < _blocksize)
return;
_srv->ReadRequest(in);
// CHECK: Discard remaining blocks
_blocksize = 0;
}
}
To copy to clipboard, switch view to plain text mode
Here's the class declaration:
class SocketHandler
: public QObject{
Q_OBJECT
public:
SocketHandler
(QLocalSocket
* ps, ServerImpl
* srv,
QObject* parent
= 0) : QObject(parent
), _ps
(ps
), _blocksize
(0), _srv
(srv
) { };
virtual ~SocketHandler() {};
public slots:
void socketReadyRead();
void onError(QLocalSocket::LocalSocketError);
void disconnected();
private:
QLocalSocket* _ps;
blocksize_t _blocksize;
ServerImpl* _srv;
};
class SocketHandler : public QObject
{
Q_OBJECT
public:
SocketHandler(QLocalSocket* ps, ServerImpl* srv, QObject* parent = 0) :
QObject(parent), _ps(ps), _blocksize(0), _srv(srv) { };
virtual ~SocketHandler() {};
public slots:
void socketReadyRead();
void onError(QLocalSocket::LocalSocketError);
void disconnected();
private:
QLocalSocket* _ps;
blocksize_t _blocksize;
ServerImpl* _srv;
};
To copy to clipboard, switch view to plain text mode
The problem, as stated above, is that I can't disconnect from server at client request. I tried QLocalSocket::close, QLocalSocket::disconnectFromServer without luck.
Should I go with a multithreaded solution? (I think it won't solve the problem).
Another solution I'm thinking is to offer a 1:1 QLocalServer<-->QLocalSocket IPC mechanism, instead of trying to handle 1:N.
Thanks in advance.
Bookmarks