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. TCP connection for file transfer
Forum Updated to NodeBB v4.3 + New Features

TCP connection for file transfer

Scheduled Pinned Locked Moved Unsolved General and Desktop
16 Posts 5 Posters 4.9k 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.
  • R robcont_

    @VRonin
    Thanks for the quick reply. I tried your code but is not working. The log is the same as what I wrote in my first post here.
    I connected my newTcpDataRead() slots to the readyRead() signal of QTcpSocket. What is not clear to me is why the transactions mechanism doesn't work properly when transferring a QImage. It seems like is not able to rebuild the data received in chunks.

    I'm new on Qt and I'm struggling on this for days.

    JonBJ Offline
    JonBJ Offline
    JonB
    wrote on last edited by
    #7

    @robcont_
    Not sure what you mean. @VRonin's code looks right to me. Transactions don't care (or know) whether QImages or anything else is being sent.

    I looked at the other question. I note you were using out.device()->seek(0);. I don't suppose that has consequences for the transactions? I didn't understand why you are doing that, why do you have to go back and put a size in instead of putting it in in the first place before the data?

    R 1 Reply Last reply
    0
    • JonBJ JonB

      @robcont_
      Not sure what you mean. @VRonin's code looks right to me. Transactions don't care (or know) whether QImages or anything else is being sent.

      I looked at the other question. I note you were using out.device()->seek(0);. I don't suppose that has consequences for the transactions? I didn't understand why you are doing that, why do you have to go back and put a size in instead of putting it in in the first place before the data?

      R Offline
      R Offline
      robcont_
      wrote on last edited by
      #8

      @JonB

      @VRonin's code looks right to me. Transactions don't care (or know) whether QImages or anything else is being sent.

      @VRonin's code is very close to what I wrote the first time (please take a look here). It works well with small data transferred (strings, numbers, lists) in a single chunk, but not with "bigger" QImage sent over TCP in many chunks. I followed the Fortune Client example , I read the documentation about QDataStream and transactions and I know it was built to simplified data streaming.
      This is why I'm not understanding what's going wrong. Any suggestion or sample code is welcome.

      I looked at the other question. I note you were using out.device()->seek(0);. I don't suppose that has consequences for the transactions? I didn't understand why you are doing that, why do you have to go back and put a size in instead of putting it in in the first place before the data?

      Because when serializing a QImage the size of eachQByteArray block to be sent is not the same as the image itself. The client side must know exactly how many bytes to read, that is the block size not the image size. Below the log of my server part.

      CameraServer: written 452690; block 452690; image 921600
      CameraServer: written 551787; block 551787; image 921600
      CameraServer: written 550869; block 550869; image 921600
      CameraServer: written 550516; block 550516; image 921600
      CameraServer: written 551006; block 551006; image 921600
      CameraServer: written 550753; block 550753; image 921600
      CameraServer: written 550669; block 550669; image 921600
      CameraServer: written 550158; block 550158; image 921600
      CameraServer: written 549714; block 549714; image 921600
      CameraServer: written 549828; block 549828; image 921600
      [...]
      
      VRoninV JonBJ 2 Replies Last reply
      0
      • R robcont_

        @JonB

        @VRonin's code looks right to me. Transactions don't care (or know) whether QImages or anything else is being sent.

        @VRonin's code is very close to what I wrote the first time (please take a look here). It works well with small data transferred (strings, numbers, lists) in a single chunk, but not with "bigger" QImage sent over TCP in many chunks. I followed the Fortune Client example , I read the documentation about QDataStream and transactions and I know it was built to simplified data streaming.
        This is why I'm not understanding what's going wrong. Any suggestion or sample code is welcome.

        I looked at the other question. I note you were using out.device()->seek(0);. I don't suppose that has consequences for the transactions? I didn't understand why you are doing that, why do you have to go back and put a size in instead of putting it in in the first place before the data?

        Because when serializing a QImage the size of eachQByteArray block to be sent is not the same as the image itself. The client side must know exactly how many bytes to read, that is the block size not the image size. Below the log of my server part.

        CameraServer: written 452690; block 452690; image 921600
        CameraServer: written 551787; block 551787; image 921600
        CameraServer: written 550869; block 550869; image 921600
        CameraServer: written 550516; block 550516; image 921600
        CameraServer: written 551006; block 551006; image 921600
        CameraServer: written 550753; block 550753; image 921600
        CameraServer: written 550669; block 550669; image 921600
        CameraServer: written 550158; block 550158; image 921600
        CameraServer: written 549714; block 549714; image 921600
        CameraServer: written 549828; block 549828; image 921600
        [...]
        
        VRoninV Offline
        VRoninV Offline
        VRonin
        wrote on last edited by
        #9

        @robcont_ said in TCP connection for file transfer:

        Because when serializing a QImage the size of eachQByteArray block to be sent is not the same as the image itself. The client side must know exactly how many bytes to read, that is the block size not the image size. Below the log of my server part.

        Datastream transactions already take care of this automatically, no need to do anything manually

        "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
        ~Napoleon Bonaparte

        On a crusade to banish setIndexWidget() from the holy land of Qt

        R 1 Reply Last reply
        1
        • VRoninV VRonin

          @robcont_ said in TCP connection for file transfer:

          Because when serializing a QImage the size of eachQByteArray block to be sent is not the same as the image itself. The client side must know exactly how many bytes to read, that is the block size not the image size. Below the log of my server part.

          Datastream transactions already take care of this automatically, no need to do anything manually

          R Offline
          R Offline
          robcont_
          wrote on last edited by robcont_
          #10

          @VRonin said in TCP connection for file transfer:

          Datastream transactions already take care of this automatically, no need to do anything manually

          I know, but the code is not working properly and I'm not understanding why. This is why I asked for help on this forum.
          As I said, when reading the stream with transactions (i.e your sample code) this is my log:

          QIODevice::ungetChar  (QTcpSocket): Called while transaction is in progress
          QIODevice::ungetChar  (QTcpSocket): Called while transaction is in progress
          QIODevice::ungetChar  (QTcpSocket): Called while transaction is in progress
          QIODevice::ungetChar  (QTcpSocket): Called while transaction is in progress
          QIODevice::ungetChar  (QTcpSocket): Called while transaction is in progress
          QIODevice::ungetChar  (QTcpSocket): Called while transaction is in progress
          QIODevice::ungetChar  (QTcpSocket): Called while transaction is in progress
          QIODevice::ungetChar  (QTcpSocket): Called while transaction is in progress
          QIODevice::ungetChar  (QTcpSocket): Called while transaction is in progress
          QIODevice::ungetChar  (QTcpSocket): Called while transaction is in progress
          QIODevice::ungetChar  (QTcpSocket): Called while transaction is in progress
          QIODevice::ungetChar  (QTcpSocket): Called while transaction is in progress
          QIODevice::ungetChar  (QTcpSocket): Called while transaction is in progress
          QIODevice::ungetChar  (QTcpSocket): Called while transaction is in progress
          QIODevice::ungetChar  (QTcpSocket): Called while transaction is in progress
          QIODevice::ungetChar  (QTcpSocket): Called while transaction is in progress
          Qimage is null!
          
          VRoninV 1 Reply Last reply
          0
          • R robcont_

            @VRonin said in TCP connection for file transfer:

            Datastream transactions already take care of this automatically, no need to do anything manually

            I know, but the code is not working properly and I'm not understanding why. This is why I asked for help on this forum.
            As I said, when reading the stream with transactions (i.e your sample code) this is my log:

            QIODevice::ungetChar  (QTcpSocket): Called while transaction is in progress
            QIODevice::ungetChar  (QTcpSocket): Called while transaction is in progress
            QIODevice::ungetChar  (QTcpSocket): Called while transaction is in progress
            QIODevice::ungetChar  (QTcpSocket): Called while transaction is in progress
            QIODevice::ungetChar  (QTcpSocket): Called while transaction is in progress
            QIODevice::ungetChar  (QTcpSocket): Called while transaction is in progress
            QIODevice::ungetChar  (QTcpSocket): Called while transaction is in progress
            QIODevice::ungetChar  (QTcpSocket): Called while transaction is in progress
            QIODevice::ungetChar  (QTcpSocket): Called while transaction is in progress
            QIODevice::ungetChar  (QTcpSocket): Called while transaction is in progress
            QIODevice::ungetChar  (QTcpSocket): Called while transaction is in progress
            QIODevice::ungetChar  (QTcpSocket): Called while transaction is in progress
            QIODevice::ungetChar  (QTcpSocket): Called while transaction is in progress
            QIODevice::ungetChar  (QTcpSocket): Called while transaction is in progress
            QIODevice::ungetChar  (QTcpSocket): Called while transaction is in progress
            QIODevice::ungetChar  (QTcpSocket): Called while transaction is in progress
            Qimage is null!
            
            VRoninV Offline
            VRoninV Offline
            VRonin
            wrote on last edited by
            #11

            @robcont_ said in TCP connection for file transfer:

            QIODevice::ungetChar (QTcpSocket): Called while transaction is in progress

            do you have 2 threads operating on the same socket?

            "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
            ~Napoleon Bonaparte

            On a crusade to banish setIndexWidget() from the holy land of Qt

            R 1 Reply Last reply
            0
            • VRoninV VRonin

              @robcont_ said in TCP connection for file transfer:

              QIODevice::ungetChar (QTcpSocket): Called while transaction is in progress

              do you have 2 threads operating on the same socket?

              R Offline
              R Offline
              robcont_
              wrote on last edited by
              #12

              @VRonin said in TCP connection for file transfer:

              do you have 2 threads operating on the same socket?

              No.
              My VCameraClient is a custom QML components, inherits from QQuickPaintedItem and manages mTcpClient. When the readyRead() signal is fired up, then the newTcpDataRead() slot is triggered. Here datastream is read and the QQuickPaintedItem is repaint through the update() method.

              1 Reply Last reply
              0
              • R robcont_

                @JonB

                @VRonin's code looks right to me. Transactions don't care (or know) whether QImages or anything else is being sent.

                @VRonin's code is very close to what I wrote the first time (please take a look here). It works well with small data transferred (strings, numbers, lists) in a single chunk, but not with "bigger" QImage sent over TCP in many chunks. I followed the Fortune Client example , I read the documentation about QDataStream and transactions and I know it was built to simplified data streaming.
                This is why I'm not understanding what's going wrong. Any suggestion or sample code is welcome.

                I looked at the other question. I note you were using out.device()->seek(0);. I don't suppose that has consequences for the transactions? I didn't understand why you are doing that, why do you have to go back and put a size in instead of putting it in in the first place before the data?

                Because when serializing a QImage the size of eachQByteArray block to be sent is not the same as the image itself. The client side must know exactly how many bytes to read, that is the block size not the image size. Below the log of my server part.

                CameraServer: written 452690; block 452690; image 921600
                CameraServer: written 551787; block 551787; image 921600
                CameraServer: written 550869; block 550869; image 921600
                CameraServer: written 550516; block 550516; image 921600
                CameraServer: written 551006; block 551006; image 921600
                CameraServer: written 550753; block 550753; image 921600
                CameraServer: written 550669; block 550669; image 921600
                CameraServer: written 550158; block 550158; image 921600
                CameraServer: written 549714; block 549714; image 921600
                CameraServer: written 549828; block 549828; image 921600
                [...]
                
                JonBJ Offline
                JonBJ Offline
                JonB
                wrote on last edited by
                #13

                @robcont_

                Because when serializing a QImage the size of eachQByteArray block to be sent is not the same as the image itself. The client side must know exactly how many bytes to read, that is the block size not the image size.

                Apart from @VRonin telling you that is not necessary, which I leave you to sort out with him/others. Even if you do need to do it your way, my issue is with your use of out.device()->seek(0); when transactions are involved. I do not know, but I'm wondering whether it might interfere with how they work. I am suggesting that to do it your way you should at least try not having to seek. Instead, serialize it to a buffer and get your size from there. Then build the block to be sent, as count followed by data, but do it left-to-right, no seeking. You should take this with a pinch of salt: if @VRonin says you need not be doing what you are, you should deal with that.

                R 1 Reply Last reply
                0
                • JonBJ JonB

                  @robcont_

                  Because when serializing a QImage the size of eachQByteArray block to be sent is not the same as the image itself. The client side must know exactly how many bytes to read, that is the block size not the image size.

                  Apart from @VRonin telling you that is not necessary, which I leave you to sort out with him/others. Even if you do need to do it your way, my issue is with your use of out.device()->seek(0); when transactions are involved. I do not know, but I'm wondering whether it might interfere with how they work. I am suggesting that to do it your way you should at least try not having to seek. Instead, serialize it to a buffer and get your size from there. Then build the block to be sent, as count followed by data, but do it left-to-right, no seeking. You should take this with a pinch of salt: if @VRonin says you need not be doing what you are, you should deal with that.

                  R Offline
                  R Offline
                  robcont_
                  wrote on last edited by robcont_
                  #14

                  @JonB said in TCP connection for file transfer:

                  Apart from @VRonin telling you that is not necessary, which I leave you to sort out with him/others.

                  I'm not arguing or questioning what @VRonin said. As I said in previous posts, I know that with transactions is not necessary to send the size of the block, in fact if you look at this post I did not.

                  Even if you do need to do it your way, my issue is with your use of out.device()->seek(0); when transactions are involved. I do not know, but I'm wondering whether it might interfere with how they work. I am suggesting that to do it your way you should at least try not having to seek. Instead, serialize it to a buffer and get your size from there. Then build the block to be sent, as count followed by data, but do it left-to-right, no seeking. You should take this with a pinch of salt: if @VRonin says you need not be doing what you are, you should deal with that.

                  I use out.device()->seek(0) in this last solution, which does NOT use transactions. Anyway, I'll try to follow your advice to buffer the stream, get the size from there and finally build the block.

                  Just for note, I tried @VRonin's code as is, but it gives the same output as mine (here).

                  JonBJ 1 Reply Last reply
                  0
                  • R robcont_

                    @JonB said in TCP connection for file transfer:

                    Apart from @VRonin telling you that is not necessary, which I leave you to sort out with him/others.

                    I'm not arguing or questioning what @VRonin said. As I said in previous posts, I know that with transactions is not necessary to send the size of the block, in fact if you look at this post I did not.

                    Even if you do need to do it your way, my issue is with your use of out.device()->seek(0); when transactions are involved. I do not know, but I'm wondering whether it might interfere with how they work. I am suggesting that to do it your way you should at least try not having to seek. Instead, serialize it to a buffer and get your size from there. Then build the block to be sent, as count followed by data, but do it left-to-right, no seeking. You should take this with a pinch of salt: if @VRonin says you need not be doing what you are, you should deal with that.

                    I use out.device()->seek(0) in this last solution, which does NOT use transactions. Anyway, I'll try to follow your advice to buffer the stream, get the size from there and finally build the block.

                    Just for note, I tried @VRonin's code as is, but it gives the same output as mine (here).

                    JonBJ Offline
                    JonBJ Offline
                    JonB
                    wrote on last edited by JonB
                    #15

                    @robcont_
                    I have a tiny/question thought for you (just guessing, I have no evidence, it might be nonsense). From your code:

                            // serialize
                            out << qint64(0) << image;
                            out.device()->seek(0);
                            out << (qint64)(block.size() - sizeof(qint64));  // the size of the block to be sent
                    

                    You subtract sizeof(qint64) to allow for your original out << qint64(0), right? But how do you know that when serialized a qint64 occupies sizeof(qint64) bytes? Maybe it does, I don't know, but maybe there is some extra serialization info stored there too??

                    Another thought is: forget about your QImage. Practice sending a block of binary data, about the same size as an image, filled with 0, 1, 2, 3, ... 255, 0, 1, ... byte values, and verify you receive exactly that at the other side too? Because whatever your issue is, it should have nothing to do with being a QImage...

                    VRoninV 1 Reply Last reply
                    3
                    • JonBJ JonB

                      @robcont_
                      I have a tiny/question thought for you (just guessing, I have no evidence, it might be nonsense). From your code:

                              // serialize
                              out << qint64(0) << image;
                              out.device()->seek(0);
                              out << (qint64)(block.size() - sizeof(qint64));  // the size of the block to be sent
                      

                      You subtract sizeof(qint64) to allow for your original out << qint64(0), right? But how do you know that when serialized a qint64 occupies sizeof(qint64) bytes? Maybe it does, I don't know, but maybe there is some extra serialization info stored there too??

                      Another thought is: forget about your QImage. Practice sending a block of binary data, about the same size as an image, filled with 0, 1, 2, 3, ... 255, 0, 1, ... byte values, and verify you receive exactly that at the other side too? Because whatever your issue is, it should have nothing to do with being a QImage...

                      VRoninV Offline
                      VRoninV Offline
                      VRonin
                      wrote on last edited by
                      #16

                      @JonB said in TCP connection for file transfer:

                      Maybe it does

                      It does, but for a more generic case you can use:

                      const qint64 originalPos = out.device()->pos();
                      out << qint64(0);
                      const qint64 sizeOfHeader = out.device()->pos() - originalPos;
                      out << image;
                      out.device()->seek(0);
                      out << static_cast<qint64>(block.size() - sizeOfHeader );
                      

                      "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                      ~Napoleon Bonaparte

                      On a crusade to banish setIndexWidget() from the holy land of Qt

                      1 Reply Last reply
                      3

                      • Login

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