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

QTcpSocket connected, but server doesn't receive data



  • Hello everyone.

    I am implementing a server with Qt 5.2 which connects to a server implemented in standard C++ (which uses standard linux lib for socket).

    My client is connecting to the server without any problems, but when I try to send something, the server doesn't receive anything, and when I look on my network activity with Wireshark, it seems that my client doesn't send anything at all because I only see TCP packet for connection establishement.

    The TCP socket is in a separate thread from the GUI, but the socket is created inside this thread, so I don't think it is a thread problem. Plus, when I debug and print the result of write functions it writes 4 or 5 (based on the string I have sent) but doesn't send anything.

    Here is my class which contains the thread
    ThreadSending.h
    @
    /**

    • @brief thread establishing connection with server and sends data to the server
    • inherits from QThread
      /
      class ThreadSending : public QThread
      {
      Q_OBJECT
      public:
      /
      *
      • @brief constructor, initiliaze IP and port
      */
      ThreadSending();

    public slots:
    /**
    * @brief the slot which receives signals sent by MainWindow
    *
    * @param val the string emitted
    */
    void addValueToList(QString val);

    private:
    /**
    * @brief method call when the thread starts
    *
    */
    void run();

    QString serverIP; /**< the IP of the server */
    int portWrite; /**< the port where it connects */
    QList <QString> toSend; /**< list of data to send */
    QMutex mutex; /**< mutex used to avoid concurrent access on list */
    

    };
    @

    ThreadSending.cpp

    @
    /**************** Sending thread *********************/
    ThreadSending::ThreadSending() : QThread()
    {
    serverIP = "192.168.0.4";
    portWrite = 1234;
    }

    void ThreadSending::addValueToList(QString val)
    {
    mutex.lock();
    toSend.append(val);
    qDebug()<<"new value to send : "<<val;
    mutex.unlock();
    }

    void ThreadSending::run()
    {
    QTcpSocket* sckWrite = new QTcpSocket();
    sckWrite->connectToHost(serverIP,portWrite);
    if(sckWrite->waitForConnected(-1))
    {
    qDebug()<<"connect sending";
    while (true)
    {
    string data = "";
    if(!toSend.isEmpty())
    {
    mutex.lock();
    data = toSend.first().toStdString();

                toSend.removeFirst();
                mutex.unlock();
    
                QString dt = QString::fromStdString(data+"\n");
                QByteArray array;
                array.append(dt);
    
                qDebug()<<"state "<<sckWrite->state();
    
                qDebug()<<"send "<<sckWrite->write(array)<<" bytes";
    
                //sckWrite->flush();
                //sckWrite->close();
            }
        }
    }
    else
        qDebug()<<"fail to connect sending";
    

    }
    @

    and my main.cpp

    @
    int main(int argc, char *argv[])
    {
    qInstallMessageHandler(debugOutput);

    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    ThreadSending* ts = new ThreadSending();
    //ThreadReceiving* tr = new ThreadReceiving();
    QObject::connect(&w, SIGNAL( valueToSend(QString) ), ts, SLOT( addValueToList(QString) ));
    ts->start();
    //tr->start();
    
    return a.exec(&#41;;
    

    }
    @

    Qt client is running on Windows 7 64bits with Qt5.2.1 and the server is runing on Ubuntu 12.04LTS 32bits
    Thank you for your help


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    Can you also post the code from the server ?



  • Thanks a lot.

    Here is my server implementation (at least for the communication with the client)

    ClientConnection.h
    @
    #ifndef CLIENTCONNECTION_INCLUDED
    #define CLIENTCONNECTION_INCLUDED

    #include <cstdio>
    #include <cstdlib>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <strings.h>

    #include "SynchronizedList.h"

    class ClientConnectionReading
    {
    public:
    ClientConnectionReading(SynchronizedList* o);
    ~ClientConnectionReading();

    void initConnection();

    bool waitForClient();
    bool waitForDataReception();

    void connectionLoop();

    private:
    int sck;
    int clientSocket;
    int port;
    struct sockaddr_in serv_addr;
    struct sockaddr_in cli_addr;

    SynchronizedList* obj;
    };

    #endif // CLIENTCONNECTION_INCLUDED
    @

    ClientConnection.cpp
    @
    #include "ClientConnection.h"

    ClientConnectionReading::ClientConnectionReading(SynchronizedList* o)
    {
    obj = o;
    }
    ClientConnectionReading::~ClientConnectionReading()
    {

    }

    void ClientConnectionReading::initConnection()
    {
    sck = socket(AF_INET, SOCK_STREAM, 0);
    if (sck < 0)
    std::cout<<"ERROR opening socket";

    bzero((char *) &serv_addr, sizeof(serv_addr));
    port = 1234;
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = INADDR_ANY;
    serv_addr.sin_port = htons(port);
    

    }

    bool ClientConnectionReading::waitForClient()
    {
    int clilen;
    if (bind(sck,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
    std::cout << "ERROR on binding";
    std::cout << "waiting for client";
    listen(sck,5);
    clilen = sizeof(cli_addr);
    clientSocket = accept(sck, (struct sockaddr ) &cli_addr, (socklen_t)&clilen);
    return true;
    }
    bool ClientConnectionReading::waitForDataReception()
    {
    int n = 0;
    char buffer[256];
    do{
    bzero(buffer,256);
    printf("before read\n");
    //sleep(1);
    n = read(clientSocket,buffer,255);
    printf("after read\n");
    //sleep(1);
    if(n==-1 || n==0)
    {
    printf("Error while reading\n");
    getchar();//wait for key strike
    }

        printf("received : %s , n : %d\n",buffer,n);
        obj->addElement( std::string(buffer) );
    } while ( true );
    return true;
    

    }

    void ClientConnectionReading::connectionLoop()
    {
    std::cout << "launching reading process";
    sleep(1);
    initConnection();
    waitForClient();
    waitForDataReception();
    }
    @

    and the main
    @
    #include "ClientConnection.h"
    #include "ClientConnectionSending.h"
    #include "HardwareCommunication.h"
    #include <pthread.h>

    void* readingThread(void* ptr)
    {
    ClientConnectionReading* obj = (ClientConnectionReading*)ptr;
    obj->connectionLoop();
    return NULL;
    }

    void* sendingThread(void* ptr)
    {
    ClientConnectionSending* obj = (ClientConnectionSending*)ptr;
    obj->connectionLoop();
    return NULL;
    }

    int main()
    {
    std::cout<<"start sever"<<std::endl;
    pthread_t t_send,t_receive;
    SynchronizedList* actionList = new SynchronizedList();
    SynchronizedList* sendList = new SynchronizedList();
    ClientConnectionReading* read = new ClientConnectionReading(actionList);
    ClientConnectionSending* send = new ClientConnectionSending(sendList);
    HardwareCommunication hwCom;

    pthread_create(&t_send,NULL,sendingThread,send);
    pthread_create(&t_receive,NULL,readingThread,read);
    std::cout << "thread launch, entering main loop"<<std::endl;
    while(1) //main thread of the app
    {
    if(sendList->isEmpty())
    {
    sleep(1);
    }
    else
    {
    std::string val = sendList->getFirstElement();
    std::string head = val.substr(0,2);
    if(head.compare("x:"))
    {
    std::string strOffset = val.substr(2);
    hwCom.setXaxis( atoi(strOffset.c_str()) );
    }
    if(head.compare("y:"))
    {
    std::string strOffset = val.substr(2);
    hwCom.setYaxis( atoi(strOffset.c_str()) );
    }
    if(head.compare("z:"))
    {
    std::string strOffset = val.substr(2);
    hwCom.setZaxis( atoi(strOffset.c_str()) );
    }
    }
    }
    delete read;
    return 0;
    }
    @

    Also I have implemented the following code in Java for testing purpose :
    @
    package test_serv;

    import java.io.IOException;
    import java.io.OutputStream;
    import java.net.Socket;
    import java.net.UnknownHostException;
    import java.util.logging.Level;
    import java.util.logging.Logger;

    /**
    *

    • @author Vince
      */
      public class Test_serv {

      /**

      • @param args the command line arguments
        */
        public static void main(String[] args) {
        Socket sck;
        OutputStream os;
        try {
        String test = "test";
        sck = new Socket("192.168.0.4",1234);
        os = sck.getOutputStream();
        os.write(test.getBytes());
        } catch (UnknownHostException ex) {
        Logger.getLogger(Test_serv.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
        Logger.getLogger(Test_serv.class.getName()).log(Level.SEVERE, null, ex);
        }
        }
        }
        @

    And it works (the server receives test correctly).


  • Lifetime Qt Champion

    One thing that puzzles me is why are you converting a QString to a std string to convert it right after to a QString and then to a QByteArray ?

    You also don't provide any means to stop your thread.

    I would recommend that you take a look at the Fortune Server/Client examples to have a better understanding on how you can use these classes without the need of threads


Log in to reply