Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Asynchronous TcpServer Share Object between Threads
QtWS25 Last Chance

Asynchronous TcpServer Share Object between Threads

Scheduled Pinned Locked Moved General and Desktop
7 Posts 3 Posters 2.2k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • B Offline
    B Offline
    buggi
    wrote on last edited by
    #1

    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! :)

    1 Reply Last reply
    0
    • T Offline
      T Offline
      t3685
      wrote on last edited by
      #2

      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.

      1 Reply Last reply
      0
      • B Offline
        B Offline
        buggi
        wrote on last edited by
        #3

        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

        1 Reply Last reply
        0
        • dheerendraD Offline
          dheerendraD Offline
          dheerendra
          Qt Champions 2022
          wrote on last edited by
          #4

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

          Dheerendra
          @Community Service
          Certified Qt Specialist
          http://www.pthinks.com

          1 Reply Last reply
          0
          • B Offline
            B Offline
            buggi
            wrote on last edited by
            #5

            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?

            1 Reply Last reply
            0
            • T Offline
              T Offline
              t3685
              wrote on last edited by
              #6

              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]

              1 Reply Last reply
              0
              • B Offline
                B Offline
                buggi
                wrote on last edited by
                #7

                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.

                1 Reply Last reply
                0

                • Login

                • Login or register to search.
                • First post
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • Users
                • Groups
                • Search
                • Get Qt Extensions
                • Unsolved