Results 1 to 12 of 12

Thread: QTcpSocket sends data twice with flush()

  1. #1
    Join Date
    Aug 2009
    Posts
    32
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default QTcpSocket sends data twice with flush()

    Hi,

    I have a strange problem where QTcpSocket sends my data twice if I call flush() following a write(). If I don't call flush the data is transmitted correctly and visible in my netcat capture. If I call flush, i see the data twice. The only time I don't have this problem while calling flush is when I wait an extended period of time before running my application a second time. I can't imagine my data is getting caught up in some OS buffer, but I have no idea what's going on. Anyone have an idea?

    Thanks.

  2. #2
    Join Date
    Aug 2009
    Posts
    32
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QTcpSocket sends data twice with flush()

    I figured it might be helpful to post the code. I've cut out most everything but a basic configuration.

    I use netcat to capture the output and provide the server side socket. I'm piping data into netcat to trigger my client side socket write:

    here's the command I use: nc -l -s 127.0.0.1 -p 7496 < zeros.txt

    zeros.txt is a 60KB file filled with ascii 0's.

    I'm using the 4.6.2 and this problem occurs on both Windows (qt creator/netcat with cygwin) and Linux.

    Here's the header:

    Qt Code:
    1. #ifndef INTERFACE_H
    2. #define INTERFACE_H
    3.  
    4. #include <QtCore>
    5. #include <QTcpSocket>
    6.  
    7. class Thread : public QThread
    8. {
    9. Q_OBJECT
    10.  
    11. public:
    12. Thread();
    13.  
    14. // Thread entry point
    15. void run(void);
    16. qint32 tx(void);
    17.  
    18. public slots:
    19. void multiplexIO(void);
    20.  
    21. private:
    22. QTcpSocket* mp_Socket;
    23. };
    24.  
    25. #endif
    To copy to clipboard, switch view to plain text mode 

    Here's the src:

    Qt Code:
    1. #include "interface.h"
    2.  
    3. int reqData=1;
    4.  
    5. ///////////////////////////////////////////////////////////////
    6. Thread::Thread()
    7. {
    8. start();
    9. }
    10.  
    11. void Thread::multiplexIO(void)
    12. {
    13. if(reqData)
    14. {
    15. qDebug() << "making request";
    16. reqData = 0;
    17. tx();
    18. }
    19. }
    20.  
    21. void Thread::run(void)
    22. {
    23. qDebug() << "thread started:" << currentThreadId();
    24.  
    25. // Create TCP interface socket
    26. mp_Socket = new QTcpSocket;
    27. mp_Socket->connectToHost("127.0.0.1", 7496);
    28.  
    29. // Wait for connection to be established
    30. if (!mp_Socket->waitForConnected(1000))
    31. {
    32. qDebug() << "Connect timed out: " << mp_Socket->errorString();
    33. return;
    34. }
    35.  
    36. // Connect our socket read routine to our signal that new data has arrived
    37. //connect(mp_Socket, SIGNAL(readyRead()), this, SLOT(multiplexIO()));
    38. connect(mp_Socket, SIGNAL(readyRead()), this, SLOT(multiplexIO()), Qt::QueuedConnection);
    39.  
    40. // Force the first call to check our socket
    41. // multiplexIO();
    42.  
    43. // Start thread's event loop
    44. exec();
    45. qDebug() << "thread terminated";
    46. }
    47.  
    48. qint32 Thread::tx()
    49. {
    50. qDebug() << "Making data request!";
    51. if(!mp_Socket)
    52. {
    53. return -1;
    54. }
    55.  
    56. mp_Socket->write("hello\n", 6);
    57. mp_Socket->flush();
    58. mp_Socket->waitForBytesWritten(10000);
    59. // mp_Socket->disconnectFromHost();
    60. return 0;
    61. }
    62.  
    63. //////////////////
    64. // Main
    65. //////////////////
    66. int main(int argc, char *argv[])
    67. {
    68. QCoreApplication core(argc, argv);
    69. Thread thread;
    70. core.exec();
    71. }
    To copy to clipboard, switch view to plain text mode 

  3. #3
    Join Date
    Feb 2008
    Posts
    491
    Thanks
    12
    Thanked 142 Times in 135 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11

    Default Re: QTcpSocket sends data twice with flush()

    I have no idea what the problem is but your code works on my Debian Sid box. I get "hello" once in a terminal flush() or no flush().

  4. #4
    Join Date
    Aug 2009
    Posts
    32
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QTcpSocket sends data twice with flush()

    Did you run it several times? I found that I had to do it 3-10 times.

    My procedure is:
    start netcat
    start app
    kill netcat
    restart netcat
    kill app
    restart app

  5. #5
    Join Date
    Feb 2008
    Posts
    491
    Thanks
    12
    Thanked 142 Times in 135 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11

    Default Re: QTcpSocket sends data twice with flush()

    Did your procedure ten times and never saw "hello" more than once.

  6. #6
    Join Date
    Aug 2009
    Posts
    32
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QTcpSocket sends data twice with flush()

    Ugh!

    Well that's strange, i can replicat this on windows and linux.

    I'm trying to code up a quick QTcpServer interface to test this w/o netcat, but I get an error that I can't create a child in a different thread from the parent:

    Qt Code:
    1. QTcpSocket* NextSock = mp_Server->nextPendingConnection();
    2. NextSock->write("p", 1);
    3. NextSock->flush();
    4. NextSock->waitForBytesWritten(10000);
    To copy to clipboard, switch view to plain text mode 

    That error doesn't make sense to me as mp_Sever is created in the same thread:

    Qt Code:
    1. void Thread2::run(void)
    2. {
    3. qDebug() << "thread started:" << currentThreadId();
    4.  
    5. // Create TCP interface socket
    6. mp_Server = new QTcpServer;
    7. mp_Server->listen(QHostAddress("127.0.0.1"), 7496);
    8.  
    9. // Connect our socket read routine to our signal that new data has arrived
    10. //connect(mp_Socket, SIGNAL(readyRead()), this, SLOT(multiplexIO()));
    11. connect(mp_Server, SIGNAL(newConnection()), this, SLOT(multiplexIO()), Qt::QueuedConnection);
    12.  
    13.  
    14. // Force the first call to check our socket
    15. // multiplexIO();
    16.  
    17. // Start thread's event loop
    18. exec();
    19. qDebug() << "thread terminated";
    20. }
    To copy to clipboard, switch view to plain text mode 

  7. #7
    Join Date
    Aug 2009
    Posts
    32
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QTcpSocket sends data twice with flush()

    Ok I think the problem is my connect() that uses "this" for the slot. Is there a way to tell the thread I want the slot to execute in the context of the newly running thread, and not the "this" parent that created the thread?

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

    Default Re: QTcpSocket sends data twice with flush()

    Did you take into consideration that readyRead() may be emitted more than once? The signal is emitted when there is something to read, not when there is everything to be read. You are probably getting two tcp segments with window size of 32kB each and processing the data fast enough to receive the readyRead() signal twice.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  9. #9
    Join Date
    Aug 2009
    Posts
    32
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QTcpSocket sends data twice with flush()

    I think I figured out my problem was the connect() using a slot on the "this" object. My multiplexIO slot is actually executing in the context of the parent event loop, and not my thread. Looking at the docs it appears calling write() on my socket from the parent thread (which I guess is what I'm actually doing) could lead to "unexpected results" as my socket's QOBJECT is owned by the executing thread. For some reason I thought by connecting a signal using the "this" ptr I would ensure my slot was executing in the context of the new thread where I called connect().

    The debug statement that specifies I am sending date is only seen once, so I didn't believe that was the problem.

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

    Default Re: QTcpSocket sends data twice with flush()

    Quote Originally Posted by xenome View Post
    I think I figured out my problem was the connect() using a slot on the "this" object. My multiplexIO slot is actually executing in the context of the parent event loop, and not my thread. Looking at the docs it appears calling write() on my socket from the parent thread (which I guess is what I'm actually doing) could lead to "unexpected results" as my socket's QOBJECT is owned by the executing thread. For some reason I thought by connecting a signal using the "this" ptr I would ensure my slot was executing in the context of the new thread where I called connect().
    QThread object doesn't represent a thread. It is more like a thread controller. Only the run() method (and objects created in it) lives in the thread controlled by the QThread object. The thread will eventually stop running but the QThread object will still be there.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  11. #11
    Join Date
    Aug 2009
    Posts
    32
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QTcpSocket sends data twice with flush()

    Right, I realize that now. My problem is that I'm trying to create a class that has a convenient API for sending/receiving specific data from a socket, but since the socket handling cannot happen in the thread class slots, I've got to create another object to perform the handling that is created in the run() which further complicates my interface.

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

    Default Re: QTcpSocket sends data twice with flush()

    Quote Originally Posted by xenome View Post
    My problem is that I'm trying to create a class that has a convenient API for sending/receiving specific data from a socket, but since the socket handling cannot happen in the thread class slots, I've got to create another object to perform the handling that is created in the run() which further complicates my interface.
    You can always push the QThread object to the thread it controls using QObject::moveToThread() but actually the first question you should ask yourself is whether you need that thread in the first place. Network traffic can be handled well in the main thread so if that's the only thing your thread does, you don't need it.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


Similar Threads

  1. Problems with maximum data sent over a QTcpSocket
    By jordip in forum Qt Programming
    Replies: 8
    Last Post: 6th July 2010, 14:34
  2. QTCPsocket data corrupt when receive
    By gabizzz in forum Qt Programming
    Replies: 2
    Last Post: 4th March 2010, 17:29
  3. QTCPSocket not getting all data
    By jhowland in forum Qt Programming
    Replies: 4
    Last Post: 29th January 2010, 15:20
  4. QTcpSocket + receiving data
    By navi1084 in forum Qt Programming
    Replies: 1
    Last Post: 2nd June 2009, 08:10
  5. Problem with reading in data from a QTCPSocket
    By Denarius in forum Qt Programming
    Replies: 4
    Last Post: 24th April 2009, 08:54

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.