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 SOCKET
QtWS25 Last Chance

TCP SOCKET

Scheduled Pinned Locked Moved General and Desktop
22 Posts 4 Posters 8.5k 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.
  • G Offline
    G Offline
    great88
    wrote on last edited by
    #7

    [quote author="code_fodder" date="1371742892"]Where is your actual QTcpSocket setup code?, I know its probably simple but post that as well let us see how its setup...[/quote]

    OK , so in my server ready_read , when a player joins the game :

    @
    void MultiClientServer::ready_read()
    {
    QTcpSocket *client = qobject_cast<QTcpSocket *>(sender());

         listOfPlayers.append(new Player("incoming string",client));
    

    // i passed the client socket to the Player constructor and added Player to list of Players

    }
    @
    The Player constructor :
    @
    QTcpSocket *socket;

    Player::Player(QString message,QTcpSocket *socket)
    {
    this->socket = socket;
    }

    QTcpSocket * Player::getSocket()
    {
    return socket;
    }
    @

    Then when I want to send data to all Players in the list :

    @
    foreach(Player *p,listOfPlayers){

                QByteArray block ;
    

    QDataStream out(&block,QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_5_0);

    out << (quint64)0;
    out << dataStr;
    out.device()->seek(0);
    out << (quint64)(block.size() - sizeof(quint64));

    p->getSocket()->write(block);
    bool success = p->getSocket()->waitForBytesWritten();

    }
    @

    1 Reply Last reply
    0
    • P Offline
      P Offline
      paolo_dc
      wrote on last edited by
      #8

      Yep, anyway it's not my thread and I was saying I've got the same problem as great88. If great88 can understand why he has got this error, maybe I will find too :)

      1 Reply Last reply
      0
      • G Offline
        G Offline
        great88
        wrote on last edited by
        #9

        Well , I hope someone will have some insight into this . Because I am stuck bad . I don't see what is wrong . Is there another way to do the reading and writing ?

        1 Reply Last reply
        0
        • C Offline
          C Offline
          ChrisW67
          wrote on last edited by
          #10

          How do you read the remainder of the packet? Reading more (or fewer) bytes than you should will leave you out-of-sync for the subsequent packet.

          1 Reply Last reply
          0
          • G Offline
            G Offline
            great88
            wrote on last edited by
            #11

            [quote author="ChrisW67" date="1371767757"]How do you read the remainder of the packet? Reading more (or fewer) bytes than you should will leave you out-of-sync for the subsequent packet.[/quote]

            Hmm , well currently I have QString data(blockSize);

            So should be reading exactly blockSize amount of data . But maybe QString isn't interpreting blockSize correctly ; I will check on that .

            @
            QDataStream in(this->sock);
            in.setVersion(QDataStream::Qt_5_0);

            if (blockSize == 0) {
              if (this->sock->bytesAvailable() < (int)sizeof(quint16))
               return;
             
              in >> blockSize;
            }
             
            if (this->sock->bytesAvailable() < blockSize)
              return;
             
            QString data(blockSize);
            in >> data;
            

            @

            1 Reply Last reply
            0
            • G Offline
              G Offline
              great88
              wrote on last edited by
              #12

              Question . Does waitForBytesWritten() prevent data ,from two different writes , from arriving at the same time
              at the client . i.e is it guaranteed that client readyRead will be called twice or no ?

              1 Reply Last reply
              0
              • C Offline
                C Offline
                ChrisW67
                wrote on last edited by
                #13

                waitForBytesWritten() waits until the bytes are written to the device or a timeout occurs, i.e. it makes no guarantees that all bytes have been sent (although typically this is true) or received. Bytes are sent in exactly the order they were added to the TCP socket.

                No. One write != one read. Written blocks may be split or coalesced by the network stack in order to make the journey.

                1 Reply Last reply
                0
                • G Offline
                  G Offline
                  great88
                  wrote on last edited by
                  #14

                  [quote author="ChrisW67" date="1371786433"]

                  No. One write != one read. Written blocks may be split or coalesced by the network stack in order to make the journey. [/quote]

                  OK , that's what I thought .

                  I think the correct way to do this on client side is this way then
                  (instead of in >> data ) :

                  QByteArray ba = socket->read(blockSize);
                  QString data = ba;

                  Problem is , conversion from QByteArray to QString is not working for me . data is empty ! How do I convert from ba to a QString ?

                  1 Reply Last reply
                  0
                  • G Offline
                    G Offline
                    great88
                    wrote on last edited by
                    #15

                    OK . SOLVED .

                    the correct client side code is :
                    @
                    QDataStream in(this->sock);
                    in.setVersion(QDataStream::Qt_5_0);

                    if (blockSize == 0) {
                         if (this->sock->bytesAvailable() < (int)sizeof(quint16))
                               return;
                         in >> blockSize;
                    }
                    

                    if (this->sock->bytesAvailable() < blockSize)
                    return;

                    QByteArray ba = this->sock->read(blockSize);

                    QDataStream in2(ba);
                    in2.setVersion(QDataStream::Qt_5_0);

                    QString data;
                    in2 >> data;
                    @

                    So basically , the blocksize is based on a ByteArray in the server . So to read it correctly on client side , use
                    QByteArray ba = this->sock->read(blockSize);
                    Since I need a QString in my code , i convert the bytearray using
                    a QDataStream .

                    1 Reply Last reply
                    0
                    • C Offline
                      C Offline
                      code_fodder
                      wrote on last edited by
                      #16

                      Regarding QString, you can instantiate QString directly from QByteArray... the two are quite compatible. I am not on my code-machine so I may get the syntax little wrong but something like this will work:

                      @
                      QByteArray ba = this->sock->read(blockSize);
                      QString qs(ba);
                      // or you can use one of the following:
                      qs.append(ba);
                      qs = ba;
                      @

                      Note that QByteArray is auto-converted into Uni code when assigning it to a QString because QString IS unicode.

                      1 Reply Last reply
                      0
                      • G Offline
                        G Offline
                        great88
                        wrote on last edited by
                        #17

                        [quote author="code_fodder" date="1371798513"]Regarding QString, you can instantiate QString directly from QByteArray... the two are quite compatible. I am not on my code-machine so I may get the syntax little wrong but something like this will work:

                        @
                        QByteArray ba = this->sock->read(blockSize);
                        QString qs(ba);
                        // or you can use one of the following:
                        qs.append(ba);
                        qs = ba;
                        @

                        [/quote]

                        Yeah , i thought it should be simple like that but it doesn't work ; the QString ends up empty . On the server side the QDataStream seems to insert a whole bunch of '\0' into the ByteArray . So when it comes back out on the client QString doesn't know how to convert it directly .
                        None of the following works in this case :
                        @
                        QString qs(ba);
                        qs.append(ba);
                        qs = ba;
                        @

                        1 Reply Last reply
                        0
                        • C Offline
                          C Offline
                          code_fodder
                          wrote on last edited by
                          #18

                          Really??,....I believe you, I am just surprised :o

                          I am out of office until Monday :( but I will look at my code, because I do this sort of thing alot... Ill get back to you on that.

                          1 Reply Last reply
                          0
                          • G Offline
                            G Offline
                            great88
                            wrote on last edited by
                            #19

                            [quote author="code_fodder" date="1371835819"]Really??,....I believe you, I am just surprised :o
                            Ill get back to you on that.[/quote]

                            Yeah , so if my QString hello is "Hello" , in the the following code , the variable block contains
                            '\0','\0','\0','\0','\0','\0','\0','&','\0','H','\0','e','\0','l','\0','l','\0','o'
                            after hello is sent to out <<

                            @
                            QByteArray block ;
                            QDataStream out(&block,QIODevice::WriteOnly);
                            out.setVersion(QDataStream::Qt_5_0);

                            out << (quint32)0;
                            out << hello;
                            out.device()->seek((quint32)0);

                            out << (quint32)(block.size() - sizeof(quint32));
                            @

                            So on the client side QString doesn't know how to translate
                            '\0','\0','\0','\0','\0','\0','\0','&','\0','H','\0','e','\0','l','\0','l','\0','o'

                            . Instead of using QString on server side i tried putting a bytearray to out << but still same problem with multiple '\0' being prefixed .

                            1 Reply Last reply
                            0
                            • C Offline
                              C Offline
                              code_fodder
                              wrote on last edited by
                              #20

                              Ah ok, I see what you are doing now...

                              So when you setup your QString what is really happening is that you are creating a "unicode" string (i.e. all values are now 16-bit and not 8-bit).

                              So the character 't' effectivly becomes '\0', 't'
                              '\0' --> '\0','\0', etc...

                              Well, that is how you would view it through "8-bit eyes".

                              I have the feeling you want to take an 8-bit QByteArray and send it as QString (unicode) and then at the other end take the unicde and turn it back to QByteArray... is that about right?

                              This is how I turn a QString (unicode) into a QByteArray (8bit):

                              @
                              uint16_t* pUtf16 = (uint16_t *) (uncompressedMsg.data());

                                      // Now move to the source string
                                      while (*pUtf16++){};
                                      _source = QString::fromUtf16(pUtf16).toLatin1();
                              

                              @

                              This code takes a uint16 pointer and points it to the data area that we are interested in (this may be your QString.data()). Then it moves past any null characters (the while loop), then comes the funcky line of code that was a real pain to figure out. It creates a QString from utf16 (unicode) and then calls the "toLatin1()" function to convert it back to 8-bit QByteArray.

                              Is that what you are trying to do?....or maybe the other way around (8bit to 16-bit unicode)?

                              You have to remember that QString IS unicode and once you make it QString you have to be careful how you use it.

                              Does that make any sense?

                              If you can avoid QString for conversion or data carrying then I would and just stick to QByteArray where possible :)
                              Also by using QString you may be doubling your data size and not knowing about it :o

                              1 Reply Last reply
                              0
                              • G Offline
                                G Offline
                                great88
                                wrote on last edited by
                                #21

                                Yeah , i would definitely prefer sending the data as QByteArray as is smaller . I will try this out , thanks much .
                                [quote author="code_fodder" date="1372073941"]

                                This is how I turn a QString (unicode) into a QByteArray (8bit):

                                @
                                uint16_t* pUtf16 = (uint16_t *) (uncompressedMsg.data());

                                        // Now move to the source string
                                        while (*pUtf16++){};
                                        _source = QString::fromUtf16(pUtf16).toLatin1();
                                

                                @

                                [/quote]

                                1 Reply Last reply
                                0
                                • C Offline
                                  C Offline
                                  code_fodder
                                  wrote on last edited by
                                  #22

                                  No problem :)

                                  Don't forget to add [Solved] to the title once you get it working (and you can post your solution if it differs from what I wrote).

                                  good luck

                                  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