Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

SIGNALS not being called when triggered.



  • Hello! I am currently creating an application that contains a server and allows other clients to connect to it. During this process I use the QTcpServer::newConnection signal, however I am having a problem with it. What I do is after a client connects to the server, the client will send a message to the server, and the server will send one to the client, kind of like a hello. The problem is that my newConnection signal is not triggering most of the time, sometimes it does, the other time it won't. The client will always say that it has connected, but my signals never fire like they should.

    Here are my initial connections for the signals / slots.

    if(m_AcceptMethod == AUTOACCEPT) connect(m_Server, &QTcpServer::newConnection, this, &MyServer::autoAccNewConn);
    
    else if(m_AcceptMethod == MANUALLYACCEPT) connect(m_Server, &QTcpServer::newConnection, this, &MyServer::manAccNewConn);
    

    There are only 2 enums, AUTOACCEPT or MANUALLYACCEPT.
    (Depending on what was chosen you will manually accept connections or you will just automatically accept them)

    Inside of the slots above I also have some more connections, these connections are done so that I can hold communication between the client, ex they connect to the server and I store their socket etc and set up a connection so I can hold communication like reading what they send to the server.

    In both original SLOTS I have the following code:

      QTcpSocket *newConnection = {m_Server->nextPendingConnection()};
    //Storing them into a vector for use elsewhere in the program
      m_Clients.append(newConnection);
    
    

    Now here is the problem, only about like 50% or less of the time the client will actually connect. On the clients program it tells me that it has successfully connected, however none of the servers signals will fire. I have found that changing the connections inside of the SLOTS above give me different ranges of success.

    connect(newConnection, &QTcpSocket::readyRead, this, &CDEServer::reading);
    ...
    void MyServer::reading()
    {
        qDebug() << "DATA FROM CLIENT IS: " << static_cast<QTcpSocket*>(sender())->readAll();
    }
    
    connect(newConnection, &QTcpSocket::readyRead, this, [newConnection, this](){
           reading(newConnection);
       });
    ...
    
    void CDEServer::reading(QTcpSocket* client)
    {
         qDebug() << "Data from the client is :" << client->readAll();
    }
    

    I don't understand why it is being so flakey, it is possible and more than likely that I am calling something, or doing something wrong, and if so PLEASE let me know what it is and how to fix it.

    Here is the automatic accept function, it is the main one I am currently working on, the manual one is not in use.

    
    //Automatically accept a new connection
    void CDEServer::autoAccNewConn(){
        qDebug() << "New Possible Connection";
        //If there are too many connections, drop the potential client
        if(m_CurrentCon >= m_MaxCon){
            //Drop the current pending connection
            dropCPenConn();
            return;
        }
    
        //The new connection will be added to the list of current connections
        QTcpSocket *newConnection = {m_Server->nextPendingConnection()};
        m_Clients.append(newConnection);
    
    
        newConnection->write("TESTING THE CONNECTION");
        newConnection->flush();
    
       /*We need to set up connections to the socket*/
       connect(newConnection, &QTcpSocket::disconnected, this, & MyServer::disconnected);
    
     connect(newConnection, &QTcpSocket::readyRead, this, [newConnection, this](){
           reading(newConnection);
       });
    
        ++m_CurrentCon;
    }
    
    ...
    
    void MyServer::reading(QTcpSocket* client)
    {
         qDebug() << "Data from the client is :" << client->readAll();
    }
    

  • Moderators

    hi @cdecde57
    The first thing I would change:
    do the writing, especially flushing, after the connect calls



  • I have made the changes, however the issue persists. :(


  • Lifetime Qt Champion

    And how do you know that the client receives your message and answers to it?



  • @Christian-Ehrlicher

    Some reason, if I put 2 qDebug functions in the reading function like this:

    qDebug() << "Hello,";
    qDebug() << "World!";

    the signal will trigger just fine and I get the messages on both ends. (Or at least most of the time it will)

    I have disconnect, connected, and write connections set up for the client and they alert that they wrote, and then connected to the server, but after that nothing happens. When things work like they should, the server and client both send messages to each other, but only some of the time.


  • Lifetime Qt Champion

    Please show your client code and your changed code with the correct connects



  • Here is my code so far. Please excuse the use of QTcpServer variable in the class, I am going to make it inherent it but I had forgotten to do that originally and will have to refactor. This also is the same for the tcpclient.

    Sorry for the late reply, I had to go to sleep.

    tcpserver.cpp

    #include "tcpserver.h"
    
    //Determine what type of accepting is used through the accept paramater and the port is the port number to listen to
    CDEServer::CDEServer(QWidget *parent) : QWidget(parent)
    {
    
    
        //Set the member variables
    
    
        //The main timer to trigger the timerEvent loop for error checks
        m_MainTimer = {new QTimer};
    
        //The message from either an error or just a status update
        QString m_ErrorMsg;
    
        //The actual server interacted with
        m_Server = {new QTcpServer};
    
        //Current number of connections
        m_CurrentCon = 0;
    
        //The IP address of the server
        m_IP = m_Server->serverAddress().toString();
    
    
        //Set the maximum number of pending connections to m_maxCon, but we have to check the current number connected before we accept any later on.
        m_Server->setMaxPendingConnections(m_MaxPCon);
    
    
    
    
    
       //start the server
       //startServer();
    
    
    }
    
    //Max connections and max pending connections
    void CDEServer::setClientMax(int maxConn, int maxPConn){
        m_MaxCon = maxConn;
        m_MaxPCon = maxPConn;
    }
    
    void CDEServer::startServer(int port, acceptMethod accept){
    
        //The port to monitor on
        m_Port = port;
    
    
        qDebug() << "Starting server...";
        //We start the server by listening on the desired port and listening on the entire netowrk
        if(!m_Server->listen(QHostAddress::Any, m_Port)){
             //Omitted error code
        }
        else{
            //Set the accept method / manually or automatically accept
            m_AcceptMethod = accept;
            //Set the signal of the server to either the automatically or manually accept new connections, function called depends on what was originally chosen by the user
            if(m_AcceptMethod == AUTOACCEPT){
                connect(m_Server, &QTcpServer::newConnection, this, &CDEServer::autoAccNewConn);
            }
            else{
                connect(m_Server, &QTcpServer::newConnection, this, &CDEServer::manAccNewConn);
            }
    
            m_Msg = "Successfully started server on port: ";
            m_Msg.append(QString::number(m_Port));
            qDebug() << m_Msg;
    
        }
    }
    
    void CDEServer::stopServer(){
        //Send out messages to clients, save files, stop the server and disconnect everyone.
    }
    
    //Automatically accept a new connection
    void CDEServer::autoAccNewConn(){
        qDebug() << "New Possible Connection";
        //If there are too many connections, drop the potential client
        if(m_CurrentCon >= m_MaxCon){
            //Drop the current pending connection
            dropCPenConn();
            return;
        }
    
        //The new connection will be added to the list of current connections
        QTcpSocket *newConnection = {m_Server->nextPendingConnection()};
        m_Clients.append(newConnection);
    
    
    
    
       /*We need to set up connections to the socket so we can read data from it and tell when we loose the connection with them.
       This way the server not only can recieve data from the client via write and flush etc, but ALSO send data to the client.*/
       connect(newConnection, &QTcpSocket::disconnected, this, &CDEServer::disconnected);
       //connect(newConnection, &QTcpSocket::readyRead, this, &CDEServer::reading);
       connect(newConnection, &QTcpSocket::readyRead, this, [newConnection, this](){
           reading(newConnection);
       });
       //connect(newConnection, &QTcpSocket::readyRead, this, &CDEServer::reading);
       newConnection->write("TESTING THE CONNECTION");
       newConnection->flush();
        ++m_CurrentCon;
    }
    
    
    //Manually accept a new connection
    void CDEServer::manAccNewConn(){
        qDebug() << "MAN-A BEGIN";
    
        //If there are too many pending connections, drop the potential client
        if(m_CurrentPCon >= m_MaxPCon){
            //Drop the current pending connection
            dropCPenConn();
            return;
        }
    
        //The new connection will be added to the list of pending connections
        QTcpSocket *newConnection{m_Server->nextPendingConnection()};
    
        //QList<QTcpSocket*>
        m_PendingC.append(newConnection);
    
        connect(newConnection, &QTcpSocket::disconnected, this, &CDEServer::disconnected);
        connect(newConnection, &QTcpSocket::readyRead, this, [newConnection, this](){
               reading(newConnection);
           });
    
        newConnection->write("You are currently on the waiting list");
        newConnection->flush();
    
        ++m_CurrentPCon;
        qDebug() << "New manual connection. ";
    }
    
    
    CDEServer::~CDEServer(){
        delete m_Server;
        m_Server = nullptr;
    }
    
    //Drop the current pending connection
    void CDEServer::dropCPenConn(){
        qDebug() << "[/!\] - MAXIMUM CAPACITY REACHED. WE HAVE DROPPED A CLIENT!!!";
        QTcpSocket *newConnection{m_Server->nextPendingConnection()};
        newConnection->write("We have reached capacity, sorry you have to be dropped.");
        newConnection->flush();
        newConnection->close();
    
        //Delete the reference to them
        delete newConnection;
        newConnection = nullptr;
    
        //Send server error saying we had to drop someone
    }
    //return the current connections list
    const QList<QTcpSocket*>& CDEServer::getConn(){
        return m_Clients;
    }
    //Return the pending clients list
    const QList<QTcpSocket*>& CDEServer::getPendingConn(){
        return m_PendingC;
    }
    
    /** SIGNALS*/
    void CDEServer::reading(QTcpSocket* client)
    {
         qDebug() << "a";
         qDebug() << "Data from the client is :" << client->readAll();
    }
    
    void CDEServer::disconnected(){
        qDebug() << "DISCONNECTED";
    }
    
    

    My tcpserver.h

    #ifndef TCPSERVER_H
    #define TCPSERVER_H
    #include <QTcpServer>
    #include <QTcpSocket>
    #include <QWidget>
    #include <QList>
    
    class CDEServer : public QWidget
    {
    
    
        //Public enums
    public:
        enum acceptMethod{
          AUTOACCEPT,
          MANUALLYACCEPT
        };
    
        //Private member variables
    private:
        //Error or message bools and variables
        bool m_HasMessage;
        bool m_ClientErr;
        bool m_ServerErr;
        QString m_Msg;
    
        //Characteristics of the server
        int m_Port;
        QString m_IP;
        acceptMethod m_AcceptMethod;
        //Max connections
        int m_MaxCon;
        //Max pending connections
        int m_MaxPCon;
        //Current number of connections
        int m_CurrentCon;
        //Current number of pending connections
        int m_CurrentPCon;
        //The actual server
        QTcpServer *m_Server;
        //The connections to our clients
        QList<QTcpSocket*> m_Clients;
        //Clients waiting to be connected to
        QList<QTcpSocket*> m_PendingC;
    
        QTimer *m_MainTimer;
    
        //Private member functions
    private:
        //Drop the current pending connection
        void dropCPenConn();
    
        //slots
    private:
        void reading(QTcpSocket* client);
        void disconnected();
    
        //Public member variables
    public:
        CDEServer(QWidget *parent = nullptr);
        void startServer(int port, acceptMethod accept);
        void stopServer();
    
        //Set the maximum and minimum connections and pending connections
        void setClientMax(int maxConn, int maxPConn);
    
        //Get the pending and current connection lists
        const QList<QTcpSocket*>& getPendingConn();
        const QList<QTcpSocket*>& getConn();
    
        ~CDEServer();
    
        //Private functions
    private:
        void autoAccNewConn();
        void manAccNewConn();
    };
    
    #endif // TCPSERVER_H
    
    

    tcpcleint.cpp

    #include "tcpclient.h"
    
    TcpClient::TcpClient(QWidget *parent) : QWidget(parent)
    {
        //Initiate the member variables
        m_Connection = {new QTcpSocket};
    
        //Set up the socket's / the server connection connections
        connect(m_Connection, &QTcpSocket::connected, this, &TcpClient::connected);
        connect(m_Connection, &QTcpSocket::disconnected, this, &TcpClient::disconnected);
        connect(m_Connection, &QTcpSocket::readyRead, this, &TcpClient::reading);
        connect(m_Connection, &QTcpSocket::bytesWritten, this, &TcpClient::writeing);
    
    
    }
    
    //Connect
    void TcpClient::connectHost(QString serverIp, int serverPort){
        //Set the desired settings to connect to.
    
        m_ServerIP = serverIp;
        m_ServerPort = serverPort;
    
        m_Connection->connectToHost(m_ServerIP, m_ServerPort);
    
    }
    
    /** Connections / slots*/
    void TcpClient::connected(){
        m_Connection->write("HELLO, WE HAVE SUCCESSFULLY CONNECTED");
        m_Connection->flush();
        qDebug() << "CONNECTED";
    }
    
    void TcpClient::disconnected(){
        qDebug() << "DISCONNECTED";
    }
    
    void TcpClient::reading(){
        qDebug() << "READING DATA\n\n\n" << m_Connection->readAll();
    }
    
    void TcpClient::writeing(){
        qDebug() << "WRITEING";
    }
    
    
    void TcpClient::errorOccured(QAbstractSocket::SocketError error){
        qDebug() << "ERROR: \n\n\n" << error;
    }
    
    

    My tcpclient.h

    #ifndef TCPCLIENT_H
    #define TCPCLIENT_H
    
    #include <QWidget>
    #include <QTcpSocket>
    #include <QString>
    #include <QAbstractSocket>
    
    class TcpClient : public QWidget
    {
        //Private member variables
    private:
        QTcpSocket *m_Connection;
        QString m_ServerIP;
        int m_ServerPort;
    
    //slots
    private:
        void connected();
        void disconnected();
        void reading();
        void writeing();
    
        void errorOccured(QAbstractSocket::SocketError error);
    //Public member functions
    public:
        TcpClient(QWidget *parent=nullptr);
    
        //Connect to a desired host
        void connectHost(QString serverIp, int serverPort);
    };
    
    #endif // TCPCLIENT_H
    
    

  • Lifetime Qt Champion

    Ok, and what do you actually see on the client and on the server side when one client connects?
    Also I would connect QAbstractSocket::errorOccoured and stateChanged to see if something went wrong



  • The server says the following when the server starts:

    Starting server...
    "Successfully started server on port: 3000" 
    //Where 3000 is the port I started it on
    

    When a client successfully connects, the sever now has the following in the debug console:

    New Possible Connection
    a
    Data from the client is : HELLO, WE HAVE SUCCESSFULLY CONNECTED
    

    The client will have the following when it successfully connects

    WRITEING
    CONNECTED
    TESTING THE CONNECTION
    

    However, when it doesn't connect write the client only has this:

    WRITEING
    CONNECTED
    

    And the server only has this:

    Starting server...
    "Successfully started server on port: 3000" 
    

    It never triggers the autoAccNewConn SLOT.

    I will go ahead and implement those connection calls you mentioned above and let you know if I can figure anything out, thank you for your help so far!



  • I added the changedState connection and this is what I got when the connection failed for the client.

     QAbstractSocket::HostLookupState
    
    
     QAbstractSocket::ConnectingState
    
    
     QAbstractSocket::ConnectedState
    
    WRITEING
    CONNECTED
    

    When it succeeds it has

     QAbstractSocket::HostLookupState
    
    
     QAbstractSocket::ConnectingState
    
    
     QAbstractSocket::ConnectedState
    
    WRITEING
    CONNECTED
    READING DATA 
    TESTING THE CONNECTION
    

  • Lifetime Qt Champion

    And do you restart the server and client every time? Do you have a firewall or similar running? I don't see anything obvious which is wrong here and not aware of any problems inside QTcpServer in Qt5.15



  • I have checked my firewall and and I restart the server, and client every time.

    I will try to rewrite a very simple server and try to connect with a single client and try to work my way back up. Thank you for your time and effort!


  • Lifetime Qt Champion

    You should start with a very simple server and client which imo should not need more than 40 lines each I would guess. This can also be posted here so we can reproduce it.



  • I created a very small server and so far it has worked just fine, I didn't change the QTcpSocket / the client code at all. I am going to slowly work my way back up and let you know how it goes.

    server.h

    #ifndef SERVER_H
    #define SERVER_H
    
    #include <QTcpSocket>
    #include <QTcpServer>
    
    class Server : public QTcpServer
    {
    public:
        Server();
        void reading();
        QTcpSocket* client;
    };
    
    #endif // SERVER_H
    

    server.cpp

    #include "server.h"
    
    Server::Server()
    {
        qDebug() << "Server is creating conections";
        connect(this, &QTcpServer::newConnection, this, [=](){
            client = this->nextPendingConnection();
            connect(client, &QTcpSocket::readyRead, this, &Server::reading);
    
            client->write("Hello, World!");
            client->flush();
        });
    
    }
    
    void Server::reading(){
        qDebug() << "Reading from the client: " << client->readAll();
    }
    
    

    Client output (Based off of the code in my previous posts)

     QAbstractSocket::HostLookupState
    
    
     QAbstractSocket::ConnectingState
    
    
     QAbstractSocket::ConnectedState
    
    WRITEING
    CONNECTED
    READING DATA 
    Hello, World!
    

    Server output

    Server is creating conections
    Reading from the client:  "HELLO, WE HAVE SUCCESSFULLY CONNECTED"
    

Log in to reply