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. Help writing non blocking TCP code
Forum Updated to NodeBB v4.3 + New Features

Help writing non blocking TCP code

Scheduled Pinned Locked Moved Unsolved General and Desktop
13 Posts 3 Posters 1.4k Views 2 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.
  • C Offline
    C Offline
    Cyrille de Brebisson
    wrote on last edited by
    #3

    Hello,

    This code uses socketStream << jsonData; to send the data...

    I am assuming that this uses the write function to do the writing...
    This means that if the message is large (10MB, 100MB for example), this call, which is in the UI thread will block the UI...

    This is problematic as my application needs the sending to happen while the rest of the UI stays active...

    In order to do that, my application saves the data to be sent and keep a "next to write" pointer in memory. Something like this (pseudo code written on the fly):

    QByteArray dataToSend; // The data that needs to be sent
    int sendingPos; // pos of the next chunk to send
    
    // Called by the user to initiate a data sending...
    void onUserTellsSystemToSend(QByteArray data)
    {
      dataToSend= data; // make a copy of the data
      sendingPos= socket.write(dataToSend.data(), min(dataToSend.count(), 10*1024)); // send the first 10K.
    }
    
    // This is connected to the socked byteWritten signal to do the rest of the sending ansychrnously
    void onByteWrittenSlot(int NbBytes)
    {
      if (sendingPos>=dataToSend.count()) // Done sending?
        dataToSend.clear;                 // clear the buffer
      else
        sendingPos+= socket.write(dataToSend.data(), min(dataToSend.count()-sendinPos, 10*1024)); // send the next 10kb...
    }
    

    But I think that even then the write in the onByteWrittenSlot function still ends up blocking as the socket inner buffer is full at this time, hence my write blocks the slot and the message queue...

    When using berkley socket in the past, I would mark my socket as non blocking and the write call would return the number of bytes that it could write without blocking, but I have not found how to do that with QT.

    Could someone confirm this?

    Cyrille

    kshegunovK 1 Reply Last reply
    0
    • C Cyrille de Brebisson

      Hello,

      This code uses socketStream << jsonData; to send the data...

      I am assuming that this uses the write function to do the writing...
      This means that if the message is large (10MB, 100MB for example), this call, which is in the UI thread will block the UI...

      This is problematic as my application needs the sending to happen while the rest of the UI stays active...

      In order to do that, my application saves the data to be sent and keep a "next to write" pointer in memory. Something like this (pseudo code written on the fly):

      QByteArray dataToSend; // The data that needs to be sent
      int sendingPos; // pos of the next chunk to send
      
      // Called by the user to initiate a data sending...
      void onUserTellsSystemToSend(QByteArray data)
      {
        dataToSend= data; // make a copy of the data
        sendingPos= socket.write(dataToSend.data(), min(dataToSend.count(), 10*1024)); // send the first 10K.
      }
      
      // This is connected to the socked byteWritten signal to do the rest of the sending ansychrnously
      void onByteWrittenSlot(int NbBytes)
      {
        if (sendingPos>=dataToSend.count()) // Done sending?
          dataToSend.clear;                 // clear the buffer
        else
          sendingPos+= socket.write(dataToSend.data(), min(dataToSend.count()-sendinPos, 10*1024)); // send the next 10kb...
      }
      

      But I think that even then the write in the onByteWrittenSlot function still ends up blocking as the socket inner buffer is full at this time, hence my write blocks the slot and the message queue...

      When using berkley socket in the past, I would mark my socket as non blocking and the write call would return the number of bytes that it could write without blocking, but I have not found how to do that with QT.

      Could someone confirm this?

      Cyrille

      kshegunovK Offline
      kshegunovK Offline
      kshegunov
      Moderators
      wrote on last edited by
      #4

      Correct. However this tutorial also provides a threaded example where the UI thread is kept disentangled from the socket operations.

      Read and abide by the Qt Code of Conduct

      C 1 Reply Last reply
      3
      • kshegunovK kshegunov

        Correct. However this tutorial also provides a threaded example where the UI thread is kept disentangled from the socket operations.

        C Offline
        C Offline
        Cyrille de Brebisson
        wrote on last edited by
        #5

        @kshegunov
        Hello, Sorry, I missed the 2nd part, since they was not much visible code, I did not spot it...

        Anyhow, what you are saying is that, in my case, I have to go threaded to solve my issues? There is no way to change the code in the onByteWrittenSlot to make it work, something like:

        // This is connected to the socked byteWritten signal to do the rest of the sending ansychrnously
        void onByteWrittenSlot(int NbBytes)
        {
          if (sendingPos>=dataToSend.count()) // Done sending?
            dataToSend.clear;                 // clear the buffer
          else {
            int nb= socket.getNumberOfBytesICanWriteWithoutBlocking();
            sendingPos+= socket.write(dataToSend.data(), min(dataToSend.count()-sendinPos, nb)); // send the next  block
          }
        }
        

        Cyrille

        kshegunovK 1 Reply Last reply
        0
        • C Cyrille de Brebisson

          @kshegunov
          Hello, Sorry, I missed the 2nd part, since they was not much visible code, I did not spot it...

          Anyhow, what you are saying is that, in my case, I have to go threaded to solve my issues? There is no way to change the code in the onByteWrittenSlot to make it work, something like:

          // This is connected to the socked byteWritten signal to do the rest of the sending ansychrnously
          void onByteWrittenSlot(int NbBytes)
          {
            if (sendingPos>=dataToSend.count()) // Done sending?
              dataToSend.clear;                 // clear the buffer
            else {
              int nb= socket.getNumberOfBytesICanWriteWithoutBlocking();
              sendingPos+= socket.write(dataToSend.data(), min(dataToSend.count()-sendinPos, nb)); // send the next  block
            }
          }
          

          Cyrille

          kshegunovK Offline
          kshegunovK Offline
          kshegunov
          Moderators
          wrote on last edited by
          #6

          @Cyrille-de-Brebisson said in Help writing non blocking TCP code:

          Anyhow, what you are saying is that, in my case, I have to go threaded to solve my issues?

          You don't "have to", strictly, but if you're working with rather big datasets it's going to be beneficial, so you don't get the network latency to show into the GUI thread.

          There is no way to change the code in the onByteWrittenSlot to make it work, something like

          However you change it it's still going to require time to flush the buffers from the socket layer to the actual network, and from Qt to the socket layer. If the data is large-ish, it can be noticeable, so that's when you'd opt for threads - when you can't tolerate the latency. In most cases you can work with the GUI thread fine, though, I'm not saying you always have to do the threading.

          (Note that Qt already buffers the data for you, so most of what you do with that second buffer isn't necessary)

          Read and abide by the Qt Code of Conduct

          C 1 Reply Last reply
          4
          • kshegunovK kshegunov

            @Cyrille-de-Brebisson said in Help writing non blocking TCP code:

            Anyhow, what you are saying is that, in my case, I have to go threaded to solve my issues?

            You don't "have to", strictly, but if you're working with rather big datasets it's going to be beneficial, so you don't get the network latency to show into the GUI thread.

            There is no way to change the code in the onByteWrittenSlot to make it work, something like

            However you change it it's still going to require time to flush the buffers from the socket layer to the actual network, and from Qt to the socket layer. If the data is large-ish, it can be noticeable, so that's when you'd opt for threads - when you can't tolerate the latency. In most cases you can work with the GUI thread fine, though, I'm not saying you always have to do the threading.

            (Note that Qt already buffers the data for you, so most of what you do with that second buffer isn't necessary)

            C Offline
            C Offline
            Cyrille de Brebisson
            wrote on last edited by
            #7

            Hello,

            @kshegunov said in Help writing non blocking TCP code:

            Note that Qt already buffers the data for you, so most of what you do with that second buffer isn't necessary)

            Does this mean that if I do a socket.write(QByteArray), regardless of the size of the byteArray, it will write the whole thing at once (ie: write will return the count of the QByteArray) as QT will buffer the array (this is assuming of course that they are no errors)?

            When is onByteWrittenSlot called? Once the whole data that was sent to write is finally fully passed through to the native network layer? or would writing 10MB to a socket cause multiple signals?

            If I reuse the above 10MB example.
            If I have a 10MB ByteArray can I do a single socket.write(array) and will I get a single onByteWrittenSlot signal in return?

            Cyrille

            kshegunovK 1 Reply Last reply
            0
            • Christian EhrlicherC Offline
              Christian EhrlicherC Offline
              Christian Ehrlicher
              Lifetime Qt Champion
              wrote on last edited by
              #8

              @Cyrille-de-Brebisson said in Help writing non blocking TCP code:

              When is onByteWrittenSlot called?

              Is perfectly documented in the signal documentation:

              This signal is emitted every time a payload of data has been written to the device's current write channel. The bytes argument is set to the number of bytes that were written in this payload.

              Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
              Visit the Qt Academy at https://academy.qt.io/catalog

              C 1 Reply Last reply
              3
              • Christian EhrlicherC Christian Ehrlicher

                @Cyrille-de-Brebisson said in Help writing non blocking TCP code:

                When is onByteWrittenSlot called?

                Is perfectly documented in the signal documentation:

                This signal is emitted every time a payload of data has been written to the device's current write channel. The bytes argument is set to the number of bytes that were written in this payload.

                C Offline
                C Offline
                Cyrille de Brebisson
                wrote on last edited by
                #9

                Hello,

                @Christian-Ehrlicher said in Help writing non blocking TCP code:

                This signal is emitted every time a payload of data has been written to the device's current write channel. The bytes argument is set to the number of bytes that were written in this payload.

                yep, I read that, what I do not know is if a "payload of data" is the equivalent of one write call or something else...

                Cyrille

                Christian EhrlicherC 1 Reply Last reply
                0
                • C Cyrille de Brebisson

                  Hello,

                  @Christian-Ehrlicher said in Help writing non blocking TCP code:

                  This signal is emitted every time a payload of data has been written to the device's current write channel. The bytes argument is set to the number of bytes that were written in this payload.

                  yep, I read that, what I do not know is if a "payload of data" is the equivalent of one write call or something else...

                  Cyrille

                  Christian EhrlicherC Offline
                  Christian EhrlicherC Offline
                  Christian Ehrlicher
                  Lifetime Qt Champion
                  wrote on last edited by Christian Ehrlicher
                  #10

                  @Cyrille-de-Brebisson It's OS-dependent and should not matter at all. The important thing is you get a progress.

                  Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                  Visit the Qt Academy at https://academy.qt.io/catalog

                  1 Reply Last reply
                  2
                  • C Cyrille de Brebisson

                    Hello,

                    @kshegunov said in Help writing non blocking TCP code:

                    Note that Qt already buffers the data for you, so most of what you do with that second buffer isn't necessary)

                    Does this mean that if I do a socket.write(QByteArray), regardless of the size of the byteArray, it will write the whole thing at once (ie: write will return the count of the QByteArray) as QT will buffer the array (this is assuming of course that they are no errors)?

                    When is onByteWrittenSlot called? Once the whole data that was sent to write is finally fully passed through to the native network layer? or would writing 10MB to a socket cause multiple signals?

                    If I reuse the above 10MB example.
                    If I have a 10MB ByteArray can I do a single socket.write(array) and will I get a single onByteWrittenSlot signal in return?

                    Cyrille

                    kshegunovK Offline
                    kshegunovK Offline
                    kshegunov
                    Moderators
                    wrote on last edited by
                    #11

                    @Cyrille-de-Brebisson said in Help writing non blocking TCP code:

                    If I have a 10MB ByteArray can I do a single socket.write(array) and will I get a single onByteWrittenSlot signal in return?

                    No you may get multiple, as Christian wrote, it still shouldn't matter.

                    Read and abide by the Qt Code of Conduct

                    1 Reply Last reply
                    1
                    • C Offline
                      C Offline
                      Cyrille de Brebisson
                      wrote on last edited by
                      #12

                      Hello,

                      What maters to me is that I would like, if possible, to not block the GUI...

                      At the moment, my socket.write calls seems to do so :-(

                      I would rather, if possible, avoid threads.

                      So, here is another formulation of the question.
                      Is there a way for me to know how many data can be "in the QT side of the pipe" so that I am not causing stalls in my write calls?

                      Then, I can monitor the differential bettwen the "byte written" signal data and what I sent through write to "throttle" my writes and stay bellow this limit. Limit which might vary per OS/network channel of course.

                      Cyrille

                      1 Reply Last reply
                      0
                      • Christian EhrlicherC Offline
                        Christian EhrlicherC Offline
                        Christian Ehrlicher
                        Lifetime Qt Champion
                        wrote on last edited by
                        #13

                        @Cyrille-de-Brebisson said in Help writing non blocking TCP code:

                        At the moment, my socket.write calls seems to do so :-(

                        But not because of the write() call since this is done async as already explained. Please provide a minimal example to reproduce the issue you're seeing.

                        Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                        Visit the Qt Academy at https://academy.qt.io/catalog

                        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