Results 1 to 15 of 15

Thread: synching client readings to server output

  1. #1

    Default synching client readings to server output

    I have a server program that writes data to datastream, and writes that to the connected client. When the client recieves the readReady() signal, it reads the data the server sent. Now, whenever I move a slider on the server app, the value of that slider is transmitted to the client. The client reads that data and moves an identical slider in the client app. When I move the server slider, the client's slider moves too, but not at the same rate I moved the server slider. It always is a bit behind, and the more I move the server slider, the farther behnd the client slider gets. Is there any way I can synch the two up, so the client doesn't eventually get several minutes worth of data behind the server?

  2. #2
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,364
    Thanks
    3
    Thanked 5,013 Times in 4,791 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: synching client readings to server output

    Strictly saying -- no. General answer -- depends. We'd have to see your code to suggest something as it depends how you implemented the transmission.

  3. #3

    Default Re: synching client readings to server output

    The server sending function:
    Qt Code:
    1. void MainWindow::sendSpeed(int amp)
    2. {
    3. QByteArray block;
    4. QDataStream out(&block, QIODevice::ReadWrite);
    5.  
    6. value = 255;
    7. out << value;
    8.  
    9. // Send the linear slider value to the client
    10. label->setNum(amp);
    11. clientConnection->write(block);
    12. statusBar->showMessage("Writing Data...", 100);
    13. }
    To copy to clipboard, switch view to plain text mode 

    The client reading function:
    Qt Code:
    1. void MainWindow::readSpeed()
    2. {
    3. QDataStream in(&tcpClient);
    4. in.setVersion(QDataStream::Qt_4_0);
    5.  
    6. quint8 sliderValue;
    7. in >> sliderValue;
    8. if (sliderValue == 0)
    9. return;
    10.  
    11. slider->setAmpValue(sliderValue);
    12. label->setNum(sliderValue);
    13. }
    To copy to clipboard, switch view to plain text mode 

    Pretty much how it works is that the valueChanged() signal from the slider is connected to the sendSpeed() slot, and tracking is turned on for the slider. The client's readyRead() signal is connected to the client's readSpeed() slot

  4. #4
    Join Date
    Jan 2006
    Location
    Germany
    Posts
    85
    Thanks
    1
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: synching client readings to server output

    Don't send every change, or even wait till the user stopped sliding if possible.

    If you want more than a smooth slider, like a fast paced game would require, I can describe you another approach that's much work but yields better results.

  5. #5
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,364
    Thanks
    3
    Thanked 5,013 Times in 4,791 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: synching client readings to server output

    You could check if there are more than one message waiting to be read, and if so, ignore all but the last one. And of course send messages only when the slider reaches its final position as already suggested.

    BTW. I think you should use a UDP socket here instead of TCP. It's not as reliable as TCP but will do here and you won't get those delays resulting from a possible retransmission. Of course the message could be lost, so think about it.

  6. #6

    Default Re: synching client readings to server output

    Well, I want it to transmit all the slider values, it's kinda supposed to be a real-time stream of the slider values, so if I move my slider, I want the client slider to move the same way. Maybe that smooth slider method would work better. How would I go about doing that, exactly?
    Last edited by OnionRingOfDoom; 28th January 2006 at 14:25.

  7. #7
    Join Date
    Jan 2006
    Location
    Germany
    Posts
    85
    Thanks
    1
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: synching client readings to server output

    First you need to implement above UDP a special protocol to transmit reliable und normal messages (unreliable). In your case we give all packets a unique increasing ID to ensure that packets that arrive out of order / late are discarded. We need this because UDP does only guarantee that if a packet arrives its contents are undamaged.

    Instead of implementing this yourself you could use a library which does this part for you, but then you would not use the Qt classes. There are HawkTL, OpenTNL, ENet and RakNet to name a few in no specific order.

    In the server you would do the following: Every time the silder value is changed imediately send an unreliable message to the client and again while sliding every x seconds a reliable message with the current state. A final reliable message after the user stopped sliding is also a good idea.
    If this produces to much unreliable packets send only every n-th change to the client.
    The client receives now the messages in any order and discards messages older than the highest ID it until now received. Since nearly all unreliable UDP messages may get lost we can only hope that after several tries a reliable message reaches the client to set the current state (will only happen with bad connections).

    That's the network part. We can now do some educated guesses based on prior information. When the user moves the slider very fast to one side we could guess that the slider will move a bit further than the current position. So your client could move the slider in a smooth way a bit further using interpolation between the last known state and the predicted new state. You could do this arbitraryly complex

  8. #8

    Default Re: synching client readings to server output

    That's uh, really pretty complicated. I kinda want it to be a bit more reliable then UDP, so I think I'll stick with TCP. If I only send like, every 3rd slider change value, will that be better? Also, how would I check to see how many items are in the que to be read, and get the latest one?

    It's kinda like it doesn't read all the data it's recieving. The client slider moves whenever I move the server slider, but it moves a lot slower than I'd like. It also stops when I stop moving my slider, but it doesn't finish going to where the server slider was when it stopped.
    Last edited by OnionRingOfDoom; 28th January 2006 at 17:43.

  9. #9
    Join Date
    Jan 2006
    Location
    Germany
    Posts
    85
    Thanks
    1
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: synching client readings to server output

    With 3 you have only around 1/3 of the packets, with 4 around 1/4... Try some values to find what suites you best.
    n = 3:
    But don't forget to send the state when the user stopped sliding otherwise your client will in 2/3 of the cases not have the final value.
    Are you already sending only every 3rd change? If yes that may be the problem.

    You can't get the newest value directly, you have to read everything from the stream (I don't know the Qt specifics here - maybe there is a method to ignore m bytes). Just read till the end of the stream discarding all old values and only using the newest to set the slider in the client.

    You can improve the TCP performance (in terms of lag) by setting certain flags: Disable Nagle's algorithm.

  10. #10

    Default Re: synching client readings to server output

    Would it have anything to do with the fact that after each valid value read by the client, it reads an additional 0? I had to set it to ignore all values of 0 for some reason...

  11. #11
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    5,372
    Thanks
    28
    Thanked 975 Times in 912 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: synching client readings to server output

    Quote Originally Posted by OnionRingOfDoom
    Would it have anything to do with the fact that after each valid value read by the client, it reads an additional 0? I had to set it to ignore all values of 0 for some reason...
    What type is that value variable of (the one you use in MainWindow::sendSpeed())?

  12. #12
    Join Date
    Jan 2006
    Location
    Germany
    Posts
    85
    Thanks
    1
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: synching client readings to server output

    Your code above is incomplete (and can't work: see lines 6 + 7 of the server). Please post the current version.

    As a general rule: Everything which you write into a stream you have to read back later in exactly the same way. Failure to do so corrupts your stream.
    Those extra values you read are probably the reason why it does not work. And why is 0 no valid value for a slider?

  13. #13
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    5,372
    Thanks
    28
    Thanked 975 Times in 912 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: synching client readings to server output

    Qt Code:
    1. void MainWindow::sendSpeed(int amp)
    2. {
    3. // QByteArray block; --- you don't need this
    4. QDataStream out( clientConnection );
    5.  
    6. // Send the linear slider value to the client
    7. label->setNum(amp);
    8. value = 255;
    9. out << value;
    10. statusBar->showMessage("Writing Data...", 100);
    11. }
    To copy to clipboard, switch view to plain text mode 

  14. #14

    Default Re: synching client readings to server output

    Jacek: the value is of the type quint 8.

    Codepoet: 0 isn't a valid value because whenever the client reads 0 is imediatly after it reads the actual value, like if it reads 8, then immediatly after that it'll read a 0, for some reason. How do I get rid of those extra values? Oh... maybe if I set it to read every other time...

  15. #15

    Default Re: synching client readings to server output

    Jacek, your fix there works perfectly! Thanks!!
    Last edited by OnionRingOfDoom; 28th January 2006 at 19:30.

Similar Threads

  1. Replies: 0
    Last Post: 22nd February 2009, 14:15
  2. Very strange socket programming problem
    By montylee in forum Qt Programming
    Replies: 5
    Last Post: 11th November 2008, 13:05
  3. How to Compile VTKDesigner2 with Qt?
    By alfredoaal in forum Newbie
    Replies: 0
    Last Post: 5th September 2008, 06:34

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.