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
Forum Updated to NodeBB v4.3 + New Features

Asynchronous TcpServer Share Object between Threads

Scheduled Pinned Locked Moved General and Desktop
7 Posts 3 Posters 2.3k Views 1 Watching
  • 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