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. QUdpSocket requires delays between writes
Forum Updated to NodeBB v4.3 + New Features

QUdpSocket requires delays between writes

Scheduled Pinned Locked Moved Solved General and Desktop
22 Posts 6 Posters 5.7k Views 4 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.
  • Kent-DorfmanK Kent-Dorfman

    Just for grins: what happens when OP takes initial post code and treats QUdpSocket as a heap object?

    myUdpSocket=new QUdpSocket()
    // do all writes quickly and sequentialls
    // sleep()
    delete myUudpSocket

    I'm curious when the QudpSocket object goes out of scope; after last reference or truly at end of main().

    M Offline
    M Offline
    Mwvse
    wrote on last edited by
    #9

    @Kent-Dorfman

    Same result.

    #include <QCoreApplication>
    #include <QUdpSocket>
    #include <QTextStream>
    #include <QThread>
    #include <QHostAddress>
    
    int main(int argc, char *argv[])
    {
    	QTextStream	cout(stdout);
    	QUdpSocket*	myUdpSocket = new QUdpSocket;
    
    	QHostAddress	addr("127.0.0.1");
    
    	myUdpSocket->connectToHost("127.0.0.1", 50000);
    
    	cout << myUdpSocket->write("msg 1\n") << Qt::endl;
    	cout << myUdpSocket->write("msg two\n") << Qt::endl;
    
    	QThread::currentThread()->sleep(5);
    
    	return 0;
    }
    
    

    Console output shows number of bytes written for each is successful:

    365f662c-7647-48e9-a639-b235d15f4431-image.png

    And wireshark shows only the 1st write made it out:

    85b0500d-7699-4aed-9b3d-6a8ff5a476de-image.png

    1 Reply Last reply
    0
    • SGaistS SGaist

      Out of curiosity, why are you not following the rule that you should first create a QCoreApplication before any QObject based classes ?

      M Offline
      M Offline
      Mwvse
      wrote on last edited by
      #10

      @SGaist

      Because I am naive :-) ?? I was just trying to exercise these library classes/methods to study them a bit. I did try the following suggestion someone posted elsewhere, but still got the same problem result:

      #include <QCoreApplication>
      #include <QUdpSocket>
      #include <QTimer>
      #include <QObject>
      #include <QDebug>
      
      class Sender: public QObject {
      	 Q_OBJECT
      public:
      	 Sender(QObject *p = nullptr):
      		  myUdpSocket(new QUdpSocket(this))    {
      		  myUdpSocket->connectToHost("127.0.0.1", 50000);
      
      		  connect(myUdpSocket, &QUdpSocket::bytesWritten, this, &Sender::sentStuff);
      
      		  QTimer::singleShot(0, this, &Sender::sendStuff);
      		  // ^^^ delays sending stuff until event loop is running
      		  //     and this timer event is processed
      	 }
      	 ~Sender() { }
      private slots:
      	 void sendStuff()
      	 {
      		  qDebug() << myUdpSocket->write("msg 1\n");
      		  qDebug() << myUdpSocket->write("msg two\n");
      	 }
      
      	 void sentStuff(qint64 bytes)
      	 {
      		  qDebug() << "Bytes sent:" << bytes;
      	 }
      private:
      	 QUdpSocket *myUdpSocket;
      };
      
      
      int main(int argc, char *argv[]) {
      	 QCoreApplication app(argc, argv);  // << application object
      	 Sender s;
      	 return app.exec();  // << event loop
      }
      
      
      #include "main.moc"
      
      

      Console output:
      fe8880e1-9aa7-4ae3-bf24-14fb8004346d-image.png

      Wireshark output:
      e1354a9a-2977-4c7b-bd12-3e77110e30e9-image.png

      kshegunovK 1 Reply Last reply
      0
      • M Mwvse

        @SGaist

        Because I am naive :-) ?? I was just trying to exercise these library classes/methods to study them a bit. I did try the following suggestion someone posted elsewhere, but still got the same problem result:

        #include <QCoreApplication>
        #include <QUdpSocket>
        #include <QTimer>
        #include <QObject>
        #include <QDebug>
        
        class Sender: public QObject {
        	 Q_OBJECT
        public:
        	 Sender(QObject *p = nullptr):
        		  myUdpSocket(new QUdpSocket(this))    {
        		  myUdpSocket->connectToHost("127.0.0.1", 50000);
        
        		  connect(myUdpSocket, &QUdpSocket::bytesWritten, this, &Sender::sentStuff);
        
        		  QTimer::singleShot(0, this, &Sender::sendStuff);
        		  // ^^^ delays sending stuff until event loop is running
        		  //     and this timer event is processed
        	 }
        	 ~Sender() { }
        private slots:
        	 void sendStuff()
        	 {
        		  qDebug() << myUdpSocket->write("msg 1\n");
        		  qDebug() << myUdpSocket->write("msg two\n");
        	 }
        
        	 void sentStuff(qint64 bytes)
        	 {
        		  qDebug() << "Bytes sent:" << bytes;
        	 }
        private:
        	 QUdpSocket *myUdpSocket;
        };
        
        
        int main(int argc, char *argv[]) {
        	 QCoreApplication app(argc, argv);  // << application object
        	 Sender s;
        	 return app.exec();  // << event loop
        }
        
        
        #include "main.moc"
        
        

        Console output:
        fe8880e1-9aa7-4ae3-bf24-14fb8004346d-image.png

        Wireshark output:
        e1354a9a-2977-4c7b-bd12-3e77110e30e9-image.png

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

        As you have wireshark opened, could you check a couple of things:

        1. That there's a bound receiver to that port
        2. If there isn't, could you check if an ARP query is being done after the first datagram goes out
        3. If there's such a query, then that's probably the answer to your question. For a detailed explanation, look here

        Also note that sending datagrams below the FastSendDatagramThreshold value in quick succession while waiting for ARP to resolve may cause datagrams to be discarded:

        ARP queues only one outbound IP datagram for a specified destination address while that IP address is being resolved to a media access control address. If a User Datagram Protocol (UDP)-based application sends multiple IP datagrams to a single destination address without any pauses between them, some of the datagrams may be dropped if there is no ARP cache entry already present. An application can compensate for this by calling the iphlpapi.dll routine SendArp() to establish an ARP cache entry, before sending the stream of packets.

        Read and abide by the Qt Code of Conduct

        M 1 Reply Last reply
        2
        • kshegunovK kshegunov

          As you have wireshark opened, could you check a couple of things:

          1. That there's a bound receiver to that port
          2. If there isn't, could you check if an ARP query is being done after the first datagram goes out
          3. If there's such a query, then that's probably the answer to your question. For a detailed explanation, look here

          Also note that sending datagrams below the FastSendDatagramThreshold value in quick succession while waiting for ARP to resolve may cause datagrams to be discarded:

          ARP queues only one outbound IP datagram for a specified destination address while that IP address is being resolved to a media access control address. If a User Datagram Protocol (UDP)-based application sends multiple IP datagrams to a single destination address without any pauses between them, some of the datagrams may be dropped if there is no ARP cache entry already present. An application can compensate for this by calling the iphlpapi.dll routine SendArp() to establish an ARP cache entry, before sending the stream of packets.

          M Offline
          M Offline
          Mwvse
          wrote on last edited by Mwvse
          #12

          Thank you very much @kshegunov for the reply.

          I have tried using netcat (under Cygwin) to listen on the port (note that only "msg 1\n" datagram arrived):

          5c2352ba-b3c0-4f35-b4f9-957927412f7c-image.png

          Here is unfiltered packet capture around the send of the first (and only datagram). Note the time stamps around my UDP message:

          223fc2ba-3328-48e5-88b3-0d1de3a02ade-image.png

          I am curious about the ARP cache as I am using the loopback device "127.0.0.1".

          kshegunovK 1 Reply Last reply
          0
          • M Mwvse

            Thank you very much @kshegunov for the reply.

            I have tried using netcat (under Cygwin) to listen on the port (note that only "msg 1\n" datagram arrived):

            5c2352ba-b3c0-4f35-b4f9-957927412f7c-image.png

            Here is unfiltered packet capture around the send of the first (and only datagram). Note the time stamps around my UDP message:

            223fc2ba-3328-48e5-88b3-0d1de3a02ade-image.png

            I am curious about the ARP cache as I am using the loopback device "127.0.0.1".

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

            @Mwvse said in QUdpSocket requires delays between writes:

            Here is unfiltered packet capture around the send of the first (and only datagram). Note the time stamps around my UDP message:

            You need to expand the Info column so you and we can see what's sent before/after the datagram. An ARP query (2 from above post) is a TCP broadcast into the subnet (I can't tell from the screenshot if that's the case here).

            Read and abide by the Qt Code of Conduct

            M 2 Replies Last reply
            0
            • kshegunovK kshegunov

              @Mwvse said in QUdpSocket requires delays between writes:

              Here is unfiltered packet capture around the send of the first (and only datagram). Note the time stamps around my UDP message:

              You need to expand the Info column so you and we can see what's sent before/after the datagram. An ARP query (2 from above post) is a TCP broadcast into the subnet (I can't tell from the screenshot if that's the case here).

              M Offline
              M Offline
              Mwvse
              wrote on last edited by Mwvse
              #14

              @kshegunov

              Sorry. I didn't consider it because the timestamps showed multiple seconds in between and thus weren't relevant (a potentially error-prone assumption):

              1c176728-6e9f-4855-81ef-a9b98e271bf4-image.png

              kshegunovK 1 Reply Last reply
              0
              • M Mwvse

                @kshegunov

                Sorry. I didn't consider it because the timestamps showed multiple seconds in between and thus weren't relevant (a potentially error-prone assumption):

                1c176728-6e9f-4855-81ef-a9b98e271bf4-image.png

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

                @Mwvse said in QUdpSocket requires delays between writes:

                Sorry. I didn't consider it because the timestamps showed multiple seconds in between and thus weren't relevant (a potentially error-prone assumption):

                Nope, it's a red herring. I don't see anything strange. Currently I have no idea why the datagram may be discarded ... Could you try another something. Modify the slot like this:

                void sendStuff()
                {
                    qDebug() << myUdpSocket->write("msg 1\n");
                    QObject::connect(myUdpSocket, &QUdpSocket::bytesWritten, myUdpSocket, [myUdpSocket] () -> void  {
                        qDebug() << myUdpSocket->write("msg two\n");
                    });
                }
                

                Does that work as expected?

                Read and abide by the Qt Code of Conduct

                M 1 Reply Last reply
                0
                • kshegunovK kshegunov

                  @Mwvse said in QUdpSocket requires delays between writes:

                  Here is unfiltered packet capture around the send of the first (and only datagram). Note the time stamps around my UDP message:

                  You need to expand the Info column so you and we can see what's sent before/after the datagram. An ARP query (2 from above post) is a TCP broadcast into the subnet (I can't tell from the screenshot if that's the case here).

                  M Offline
                  M Offline
                  Mwvse
                  wrote on last edited by Mwvse
                  #16

                  @kshegunov

                  I am curious about the ARP cache problem and being on 127.0.0.1.

                  1 Reply Last reply
                  1
                  • kshegunovK kshegunov

                    @Mwvse said in QUdpSocket requires delays between writes:

                    Sorry. I didn't consider it because the timestamps showed multiple seconds in between and thus weren't relevant (a potentially error-prone assumption):

                    Nope, it's a red herring. I don't see anything strange. Currently I have no idea why the datagram may be discarded ... Could you try another something. Modify the slot like this:

                    void sendStuff()
                    {
                        qDebug() << myUdpSocket->write("msg 1\n");
                        QObject::connect(myUdpSocket, &QUdpSocket::bytesWritten, myUdpSocket, [myUdpSocket] () -> void  {
                            qDebug() << myUdpSocket->write("msg two\n");
                        });
                    }
                    

                    Does that work as expected?

                    M Offline
                    M Offline
                    Mwvse
                    wrote on last edited by kshegunov
                    #17

                    [Edit: Sorry I deleted your post by accident. I feel real dumb right now ~kshegunov]

                    1 Reply Last reply
                    0
                    • kshegunovK Offline
                      kshegunovK Offline
                      kshegunov
                      Moderators
                      wrote on last edited by kshegunov
                      #18

                      Yes, my bad:

                      void sendStuff()
                      {
                          QObject::connect(myUdpSocket, &QUdpSocket::bytesWritten, this, [this] () -> void  {
                              QObject::disconnect(myUdpSocket, nullptr, this, nullptr);// To prevent looping
                              qDebug() << myUdpSocket->write("msg two\n");
                          });
                          qDebug() << myUdpSocket->write("msg 1\n");
                      }

                      Read and abide by the Qt Code of Conduct

                      M 1 Reply Last reply
                      0
                      • kshegunovK kshegunov

                        Yes, my bad:

                        void sendStuff()
                        {
                            QObject::connect(myUdpSocket, &QUdpSocket::bytesWritten, this, [this] () -> void  {
                                QObject::disconnect(myUdpSocket, nullptr, this, nullptr);// To prevent looping
                                qDebug() << myUdpSocket->write("msg two\n");
                            });
                            qDebug() << myUdpSocket->write("msg 1\n");
                        }
                        M Offline
                        M Offline
                        Mwvse
                        wrote on last edited by
                        #19

                        @kshegunov

                        Packet capture looks the same. Console output only shows first write.

                        6a24dbd4-4a3d-435b-a812-76d1a4dadf55-image.png

                        kshegunovK 1 Reply Last reply
                        0
                        • M Mwvse

                          @kshegunov

                          Packet capture looks the same. Console output only shows first write.

                          6a24dbd4-4a3d-435b-a812-76d1a4dadf55-image.png

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

                          This is very strange. I'm currently out of ideas ... :|

                          Read and abide by the Qt Code of Conduct

                          M 1 Reply Last reply
                          0
                          • kshegunovK kshegunov

                            This is very strange. I'm currently out of ideas ... :|

                            M Offline
                            M Offline
                            Mwvse
                            wrote on last edited by Mwvse
                            #21

                            @kshegunov

                            Going back to your comment:

                            "ARP queues only one outbound IP datagram for a specified destination address while that IP address is being resolved to a media access control address. If a User Datagram Protocol (UDP)-based application sends multiple IP datagrams to a single destination address without any pauses between them, some of the datagrams may be dropped if there is no ARP cache entry already present. An application can compensate for this by calling the iphlpapi.dll routine SendArp() to establish an ARP cache entry, before sending the stream of packets."

                            I did the following:

                            #include <QCoreApplication>
                            #include <QUdpSocket>
                            #include <QTextStream>
                            #include <QThread>
                            
                            int main(int argc, char *argv[])
                            {
                            	QCoreApplication app(argc, argv);
                            
                            	QTextStream	cout(stdout);
                            	QUdpSocket*	myUdpSocket = new QUdpSocket;
                            
                            	myUdpSocket->connectToHost("127.0.0.1", 50000);
                            
                            	cout << myUdpSocket->write("msg 1\n") << Qt::endl;
                            	QThread::currentThread()->sleep(1);
                            
                            	for(unsigned u = 0; u < 100; u++)
                            		cout << myUdpSocket->write("another\n") << Qt::endl;
                            
                            	QThread::currentThread()->sleep(5);
                            
                            	return 0;
                            }
                            
                            

                            As long as I have a delay after the first write, I get all 100 of the following at full speed. So ... something in the IP stack needs to get established. That first write seems to do it although it takes some time. I am wondering if since we are on 127.0.0.1 the ARP never goes out but the net result is the ARP cache gets created and then off we go.

                            Anyway, thank you very much for your time and expertise. I don't have a Linux box handy at the moment but I am curious if I get similar results. If I get a chance, I will try it and post the results here just for the record.

                            kshegunovK 1 Reply Last reply
                            1
                            • M Mwvse

                              @kshegunov

                              Going back to your comment:

                              "ARP queues only one outbound IP datagram for a specified destination address while that IP address is being resolved to a media access control address. If a User Datagram Protocol (UDP)-based application sends multiple IP datagrams to a single destination address without any pauses between them, some of the datagrams may be dropped if there is no ARP cache entry already present. An application can compensate for this by calling the iphlpapi.dll routine SendArp() to establish an ARP cache entry, before sending the stream of packets."

                              I did the following:

                              #include <QCoreApplication>
                              #include <QUdpSocket>
                              #include <QTextStream>
                              #include <QThread>
                              
                              int main(int argc, char *argv[])
                              {
                              	QCoreApplication app(argc, argv);
                              
                              	QTextStream	cout(stdout);
                              	QUdpSocket*	myUdpSocket = new QUdpSocket;
                              
                              	myUdpSocket->connectToHost("127.0.0.1", 50000);
                              
                              	cout << myUdpSocket->write("msg 1\n") << Qt::endl;
                              	QThread::currentThread()->sleep(1);
                              
                              	for(unsigned u = 0; u < 100; u++)
                              		cout << myUdpSocket->write("another\n") << Qt::endl;
                              
                              	QThread::currentThread()->sleep(5);
                              
                              	return 0;
                              }
                              
                              

                              As long as I have a delay after the first write, I get all 100 of the following at full speed. So ... something in the IP stack needs to get established. That first write seems to do it although it takes some time. I am wondering if since we are on 127.0.0.1 the ARP never goes out but the net result is the ARP cache gets created and then off we go.

                              Anyway, thank you very much for your time and expertise. I don't have a Linux box handy at the moment but I am curious if I get similar results. If I get a chance, I will try it and post the results here just for the record.

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

                              @Mwvse said in QUdpSocket requires delays between writes:

                              As long as I have a delay after the first write, I get all 100 of the following at full speed. So ... something in the IP stack needs to get established. That first write seems to do it although it takes some time. I am wondering if since we are on 127.0.0.1 the ARP never goes out but the net result is the ARP cache gets created and then off we go.

                              Yes, this would seem to support that hypothesis indeed, but I didn't see a TCP broadcast in wireshark. In any case something very windows specific may be going on (which has nothing to do with Qt apparently). On the other hand if this turns out to be the case, I think Qt can do better to wait for the ARP cache to be built before sending the following datagrams.

                              If I get a chance, I will try it and post the results here just for the record.

                              This would be much appreciated.

                              Read and abide by the Qt Code of Conduct

                              1 Reply Last reply
                              1

                              • Login

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