Important: Please read the Qt Code of Conduct -

[Solved] QTcpSocket not writing to socket

  • UPDATE: this thread was original entitled No readyRead() signal being sent in threaded server application but the nature of the problem seems to be more related to the sending of the signal rather than the receiving. Details are in the third post

    I am fairly new to Qt and qt networking in particular. I am having an issue where sending data is not triggering the thread function that reads the data. (the QTcpSocket class I created sets up a thread to communicate with each machine that connects). I am assuming that this is because the readyRead signal is not being emitted.

    I may have figured out why but before I get into those details let me just make sure that the scenario I have created is a valid one.

    I am creating an application that is extremely modularized and is capable of acting as a client, a server, or both depending on the user's credentials and the functionality the application is set up for on a specific machine. In normal use this application would NOT be talking back and forth as both client and server because it is meant to be distributed in nodes across a network. (i.e. an administrator can set up a node to act as a server that passes on requests it is not set up to deal with... hence it acts as a server and a client).

    However... in the test case all functionality is on one machine. So the client and server talk to each other within the same application instance. Is this a valid scenario? (i.e. can this work?)

    I am assuming at this point this will work. So on to our problem.

    I think the issue is that I am simply writing to a socket on the client side without calling waitForBytesWritten(). I am assuming that the "ready" signal is not being sent along the network because the write() call doesn't assume that the entire body of what needs to be sent is ready for sending. Therefore it is not actually being written to the socket but put in a buffer to be sent.

    Unfortunately this application is to be used on windows machines and the documentation says that calling waitForBytesWritten() randomly does not work on Windows. So I will need to redesign the way this is handled (using the byteswritten signal). This will take some time but I thought it would be good to ask these questions in the mean time so that I can make sure I am headed in the right direction.

  • Perhaps I didn't make the second (and main question) clear: Considering that I cannot use waitForBytesWritten(), what do I use to force the client to send the data to the server?

  • Ok... this is really getting aggravating. The only solution I have found so far is to use QTcpSocket.flush(). But even if I set up a signal and socket connection to handle the signal this should generate, nothing happens. So it is time to post some code.

    Here is the code that generates the tcp socket. It is part of "main" because my splash screen contains the login screen and the login data to send is generated there. w is the main window class instance while a is the application class

    int main(int argc, char *argv[])
    // creates splash
    // detects network configuration ... saves in w
    // loads application settings... saves in w
    // handles arguments
    // shows login widgets and waits for user input

    while (waitForResponse)
    QTcpSocket loginSocket;
    if (w.getServerAddress() == QString("LOCAL"))
    loginSocket.connectToHost(w.getHostAddressIn()->toString(), (quint16)ServerPorts::loginRequest);
    loginSocket.connectToHost(*w.getServerAddress(), (quint16)ServerPorts::loginRequest);

    // generate datastream using username and password
    // code for connecting the socket which works fine...

    // HERE is the code that calls the code that doesn't get a response...
    w.sendLoginData(dataStream->data(), &loginSocket);
    while (w.isSendingLogin())
    a.processEvents(); // THE PROGRAM NEVER LEAVES THIS LOOP


    Here are the two functions called by the previous code. It may be important to note that the client engine class referred to is in a separate dll and namespace. My guess is that fact separates the code from the main window's event loop.

    bool MyWindow::isSendingLogin() { return mClientEngine->isSendingData(); }

    void MyWindow::sendLoginData(const char* data, QTcpSocket* socket)
    if (mClientEngine == NULL)
    mClientEngine = new ClientEngine(this);

    mClientEngine->sendDataToServer(data, socket);

    Here is the code from the dynamically loaded engine called by the above functions. This includes the code that performs the flush AND the slot that is supposed to be called as a result.

    void ClientEngine::sendDataToServer(const char* data, QTcpSocket* socket)
    mBytesSentCount = 0;
    mOutgoingSocket = (QTcpSocket*)socket;
    connect(socket, SIGNAL(bytesWritten(qint64 bytes)), this, SLOT(dataSent(qint64 bytes)));
    mOutgoingByteCount = socket->write(data);

    void ClientEngine::dataSent(qint64 bytes) // SLOT referred to in above connection that NEVER GETS CALLED
    mBytesSentCount += bytes;
    if (mBytesSentCount >= mOutgoingByteCount)
    disconnect(mOutgoingSocket, SIGNAL(bytesWritten(qint64 bytes)), this, SLOT(dataSent(qint64 bytes)));
    mOutgoingSocket = NULL;

    bool ClientEngine::isSendingData() const { return mOutgoingSocket != NULL; }

    My best guess is that because the engine is in a separate dll, that somehow its signals are being left out of the event loop... Not sure how I would fix that... or if it is even the problem.

Log in to reply