paxdiablo paxdiablo - 10 months ago 73
C++ Question

Use select() within Qt for monitoring of multiple ports, or is there a better way?

I have a need for a very simple server program which executes one of five different activities, based on client connections.

Since this is for a demo, I don't need any complex network handling, my intention was just to open up five server sockets (say

inclusive) and simply await incoming connections.

Upon the server receiving an incoming connection on (for example) the first socket
, it would immediately accept and close the connection, then execute the first action. Ditto for the other sockets. That way, I could demo the actions from another window simply by executing:

telnet 10001

Normally, I would use
with a very short timeout value (i.e., not too onerous on the event processing thread) to await and detect which port was being connected to but, since this is a Qt application, I'm not sure that will work so well with the Qt event model.

What would be the best way of doing this with Qt (5.5, if it matters)? Is the use of a small-timeout
actually going to work or do I need to go heavyweight with five separate
objects, each with their own infrastructure (callbacks and such)?

Answer Source

If I properly understand, you want handle all requests in one place. In Qt you can use signal/slot for it. Connect signals from all QTcpServer objects to one slot, something like:

// Method to fully start a server on specific port.

QTcpServer *MyClass::StartServer(int port) {
    QTcpServer *server = new QTcpServer();
    server->listen(QHostAddress::Any, port);
    connect(server, SIGNAL(newConnection()), this, SLOT(HandleConn()));
    return server;

// Method to start all servers, serverArr is an array of QTcpServer
//   items (in the object, obviously).

void MyClass::StartAllServers() {
    for (size_t i = 0; i < sizeof(serverArr) / sizeof(*serverArr); i++)
        serverArr[i] = StartServer(10000 + i);

// Callback to handle connections.

void MyClass::HandleConn() {
    // This will call doAction with parameter based on which QTcpServer
    //   has caused the callback.

    QTcpServer *source = static_cast<QTcpServer*>(sender());
    for (size_t i = 0; i < sizeof(serverArr) / sizeof(*serverArr); i++)
        if (source == serverArr[i])

    // Action done, so just accept and close connection.

    QTcpSocket *socket = source->nextPendingConnection();