Asynchronous TcpServer Share Object between Threads



  • Hello everyone,
    I have a TcpServer up and running. As soon as a client connects I create a new socket and when the client is ready, I start my new Thread with the Task I want it to do. Now when I am ready executing and want to write my Task-result to the socket I have to work with Signal&Slots to make the Socket-Thread send my result. But what I want to do is, send the result directly from the Task-Thread. I tried passing the pointer to the socket to the Result-Thread and write to it, but this only gives me a Warning on runtime: QObject: Cannot create children for a parent that is in a different thread. (Parent is QNativeSocketEngine(0x11d7b10), parent's thread is QThread(0xfa9f40), current thread is QThread(0x101cac0). So maybe you can help me avoid Signals&Slots here.

    So this is the Method for creating the Socket:
    @
    void MyClient::CreatSocket(qintptr handle)
    {
    socket = new QTcpSocket(this);

    socket->setSocketDescriptor(handle);
    
    connect(socket, SIGNAL(connected()), this, SLOT(connected()));
    connect(socket, SIGNAL(disconnected()), this, SLOT(disconnected()));
    connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead()));
    

    }
    @

    and here I create the new Task as soon as the Client is ready, and give it the socket.
    @
    void MyClient::readyRead()
    {
    task = new MyTask();
    task->setAutoDelete (true);

    task->SetSocket(socket);
    task->SetFilename(FileName);
    
    QThreadPool::globalInstance()->start(task);
    

    }
    @

    This is the Set Socket Function:
    @
    void MyTask::SetSocket(QTcpSocket *socket)
    {
    socket = socket;
    }
    @

    and last but not least the run Method of MyTask:
    @
    void MyTask::run()
    {
    QString non = "This is Sparta!!!!";

    if(socket->isWritable())
    {
        int written = socket->write(non.toUtf8());
        if(written == -1)
        {
            qWarning() << "Data could not be written to Socket!";
        }
        else
        {
            qDebug()<<"Non written to Socket";
        }
    }
    else
    {
        qWarning() << "Socket is not writable!";
    }
    

    @

    Thank you in advance! :)



  • You cannot read/write with a QTcpSocket in another thread than the one that created the Object.

    Is there a reason why you want to write from the other thread, because

    @QTcpSocket::write@

    returns immediately causing no delay in your application.



  • Thanks for your reply!
    Yes the reason is I'm lazy ;) In my Task-Thread I look at what the Client send me and check if he wants something back, when he wants something I have to send it like here:
    "tmp" is the string I get from the socket/client.

    @
    if(tmp.contains("newcycle"))
    {
    tmp = tmp.replace("newcycle;","\n");
    WriteData(tmp);
    }
    else if (tmp.contains("write"))
    {
    tmp = tmp.replace("write,","");
    WriteData(tmp);
    }
    else if (tmp.contains("get_x_pos"))
    {
    emit send_x_pos();
    }
    else if(tmp.contains("get_y_pos"))
    {
    emit send_y_pos();
    }
    else if(tmp.contains("get_z_pos"))
    {
    emit send_z_pos();
    }
    @

    And I have a huge amount of these "get_something" and "set_something"
    and for every command I want to receive from the client I have to implement a Signal&Slot. Would make live much easier if I could send back the data right in the Task-Thread instead of emitting the signal.

    And I am open for a complete redesign of my mechanism if that would make adding these "If(tmp.contains(...))" easy:D



  • Try changing the ownership of serversocket. I have not tried this. It should work. You can use myObject->moveToThread(...)



  • Ok so I do it like this:
    @socket->moveToThread(...)@

    my Problem is when I start the Thread like this:
    @ QThreadPool::globalInstance()->start(task);@

    how do I find out what Thread I have to move the socket to?



  • You could simply make one slot

    @void sendData(QString)@

    and one signal

    @void dataReady(QString)@

    and in your worker, determine what the string needs to be and emit dataReady.

    [quote author="buggi" date="1390469097"]Thanks for your reply!
    Yes the reason is I'm lazy ;) In my Task-Thread I look at what the Client send me and check if he wants something back, when he wants something I have to send it like here:
    "tmp" is the string I get from the socket/client.

    @
    if(tmp.contains("newcycle"))
    {
    tmp = tmp.replace("newcycle;","\n");
    WriteData(tmp);
    }
    else if (tmp.contains("write"))
    {
    tmp = tmp.replace("write,","");
    WriteData(tmp);
    }
    else if (tmp.contains("get_x_pos"))
    {
    emit send_x_pos();
    }
    else if(tmp.contains("get_y_pos"))
    {
    emit send_y_pos();
    }
    else if(tmp.contains("get_z_pos"))
    {
    emit send_z_pos();
    }
    @

    And I have a huge amount of these "get_something" and "set_something"
    and for every command I want to receive from the client I have to implement a Signal&Slot. Would make live much easier if I could send back the data right in the Task-Thread instead of emitting the signal.

    And I am open for a complete redesign of my mechanism if that would make adding these "If(tmp.contains(...))" easy:D[/quote]



  • Thank you for this response!
    I had this Idea too and it looks like there is no better way to do it.

    I will try it.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.