Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

[Windows] First QUdpSocket::bind blocks for three seconds


  • Lifetime Qt Champion

    Hi all,

    I have a small tool that scans for Lantronix Xports in the local network by UDP broadcast and collects the answers.

    That works well if the system has only one network interface. To listen on multiple interfaces, I wrote the following:

    static QString now()
    {
    	return QTime::currentTime().toString("HH:mm:ss:zzz");
    }
    
    Xport::Xport(QObject *parent) :
    	QObject(parent)
    {
    	qDebug() << now() << "start";
    
    	foreach (QHostAddress address, QNetworkInterface::allAddresses()) {
    		if (address.protocol() != QAbstractSocket::IPv4Protocol)
    			continue;
    		if (address.isLoopback())
    			continue;
    
    		m_allAddresses.append(address);
    
    		QUdpSocket *socket = new QUdpSocket(this);
    		if (socket->bind(address, 8000, QUdpSocket::ShareAddress)) {
    			qDebug() << now() << "Bound UDP socket to address:" << address.toString();
    			connect(socket, SIGNAL(readyRead()), this, SLOT(udpDatagramReceived()));
    			m_addresses.insert(socket, address.toString());
    		} else {
    			qDebug() << now() << "Cannot bind UDP socket to address:" << address.toString();
    		}
    	}
    }
    

    This gives the following output:

    "09:59:49:286" start
    "09:59:52:476" Cannot bind UDP socket to address: "169.254.25.130"
    "09:59:52:477" Cannot bind UDP socket to address: "169.254.11.18"
    "09:59:52:478" Cannot bind UDP socket to address: "169.254.68.104"
    "09:59:52:479" Cannot bind UDP socket to address: "169.254.161.5"
    "09:59:52:480" Bound UDP socket to address: "192.168.16.56"
    "09:59:52:481" Bound UDP socket to address: "192.168.25.56"
    "09:59:52:482" Bound UDP socket to address: "192.168.56.1"
    

    As you can see, all binds except the first are very fast. Any idea why this happens? Do I really have to use threads to workaround this?

    Thanks in advance

    Edit: Qt 5.9.7 MinGW 32



  • Any chance you can inspect which part of QAbstractSocketPrivate::initSocketLayer is the bottleneck? I realise on windows it's not straightforward to have a dev environment for Qt set up but I thought I'd try


  • Lifetime Qt Champion

    @VRonin Unfortunately not now (and honestly I didn't want to dig that deep into), but thanks for the hint. Maybe I'll try.


  • Lifetime Qt Champion

    I've no delay here on my system. First thought it is maybe due to 'QNetworkProxy::setApplicationProxy(QNetworkProxy())' in my testcase but it doesn't matter.
    Maybe a dns resolve delay?


  • Moderators

    @aha_1980 to test @Christian-Ehrlicher s theory, you could shuffel your QHostAdress list, if it changes anything.

    QList<QHostAddress> addresses = QNetworkInterface::allAddresses();
    std:shuffle(addresses.start(), addresses.end());
    
    foreach (QHostAddress address, addresses)  {
    ....
    

  • Qt Champions 2017

    IP address starting with 169.254.x.x are useless IP address. It is better you filter then bind them. These address indicates some configuration issue. Can you also run 'ifconfig /all command' and show me the output ? I'm wondering why so many 169.254... address on your box.


  • Lifetime Qt Champion

    @dheerendra They are not useless. These are self assigned IP which are used when you connect directly devices together without any dhcp server between them e.g. direct cable connection from your computer to a network camera.

    You can then use something like zeroconf to find the devices (if they do advertise something using that protocol).


  • Lifetime Qt Champion

    Hi
    Its quite normal ips and the concept is called Automatic Private IP Addressing.
    https://wiki.wireshark.org/APIPA


  • Qt Champions 2017

    @SGaist as you said they are assigned without DHCP server. These are internally allocated and not known to user. This is where my point came as useless. IP addresses should be either statically assigned by user or configured from DHCP. Then these address will be usable.


  • Lifetime Qt Champion

    @dheerendra

    You're right, there are a lot of IP addresses. I don't know why, I got the laptop in this state ;) But I'll try to filter them out.

    Here is the ifconfig output:

    
    Windows-IP-Konfiguration
    
       Hostname  . . . . . . . . . . . . : AHNB
       Primäres DNS-Suffix . . . . . . . : 
       Knotentyp . . . . . . . . . . . . : Hybrid
       IP-Routing aktiviert  . . . . . . : Nein
       WINS-Proxy aktiviert  . . . . . . : Nein
    
    Ethernet-Adapter Bluetooth-Netzwerkverbindung:
    
       Medienstatus. . . . . . . . . . . : Medium getrennt
       Verbindungsspezifisches DNS-Suffix: 
       Beschreibung. . . . . . . . . . . : Bluetooth-Gerät (PAN)
       Physikalische Adresse . . . . . . : AC-2B-6E-DB-86-C9
       DHCP aktiviert. . . . . . . . . . : Ja
       Autokonfiguration aktiviert . . . : Ja
    
    Drahtlos-LAN-Adapter Drahtlosnetzwerkverbindung 3:
    
       Medienstatus. . . . . . . . . . . : Medium getrennt
       Verbindungsspezifisches DNS-Suffix: 
       Beschreibung. . . . . . . . . . . : Microsoft Virtual WiFi Miniport Adapter #2
       Physikalische Adresse . . . . . . : AE-2B-6E-DB-86-C5
       DHCP aktiviert. . . . . . . . . . : Ja
       Autokonfiguration aktiviert . . . : Ja
    
    Drahtlos-LAN-Adapter Drahtlosnetzwerkverbindung 2:
    
       Medienstatus. . . . . . . . . . . : Medium getrennt
       Verbindungsspezifisches DNS-Suffix: 
       Beschreibung. . . . . . . . . . . : Microsoft Virtual WiFi Miniport Adapter
       Physikalische Adresse . . . . . . : AE-2B-6E-DB-86-C6
       DHCP aktiviert. . . . . . . . . . : Ja
       Autokonfiguration aktiviert . . . : Ja
    
    Drahtlos-LAN-Adapter Drahtlosnetzwerkverbindung:
    
       Medienstatus. . . . . . . . . . . : Medium getrennt
       Verbindungsspezifisches DNS-Suffix: wifirst.net
       Beschreibung. . . . . . . . . . . : Intel(R) Dual Band Wireless-AC 3165
       Physikalische Adresse . . . . . . : AC-2B-6E-DB-86-C5
       DHCP aktiviert. . . . . . . . . . : Ja
       Autokonfiguration aktiviert . . . : Ja
    
    Ethernet-Adapter LAN-Verbindung:
    
       Verbindungsspezifisches DNS-Suffix: 
       Beschreibung. . . . . . . . . . . : Intel(R) Ethernet Connection I219-V
       Physikalische Adresse . . . . . . : C8-5B-76-20-29-F1
       DHCP aktiviert. . . . . . . . . . : Nein
       Autokonfiguration aktiviert . . . : Ja
       Verbindungslokale IPv6-Adresse  . : fe80::9973:92be:7a06:90d2%11(Bevorzugt) 
       IPv4-Adresse  . . . . . . . . . . : 192.168.16.56(Bevorzugt) 
       Subnetzmaske  . . . . . . . . . . : 255.255.255.0
       IPv4-Adresse  . . . . . . . . . . : 192.168.25.56(Bevorzugt) 
       Subnetzmaske  . . . . . . . . . . : 255.255.255.0
       Standardgateway . . . . . . . . . : 192.168.25.1
       DHCPv6-IAID . . . . . . . . . . . : 248011638
       DHCPv6-Client-DUID. . . . . . . . : 00-01-00-01-1E-FA-29-B0-C8-5B-76-20-29-F1
       DNS-Server  . . . . . . . . . . . : 192.168.25.1
                                           192.168.16.5
       NetBIOS über TCP/IP . . . . . . . : Aktiviert
    
    Ethernet-Adapter VirtualBox Host-Only Network:
    
       Verbindungsspezifisches DNS-Suffix: 
       Beschreibung. . . . . . . . . . . : VirtualBox Host-Only Ethernet Adapter
       Physikalische Adresse . . . . . . : 0A-00-27-00-00-1A
       DHCP aktiviert. . . . . . . . . . : Nein
       Autokonfiguration aktiviert . . . : Ja
       Verbindungslokale IPv6-Adresse  . : fe80::c876:59bb:672:4b63%26(Bevorzugt) 
       IPv4-Adresse  . . . . . . . . . . : 192.168.56.1(Bevorzugt) 
       Subnetzmaske  . . . . . . . . . . : 255.255.255.0
       Standardgateway . . . . . . . . . : 
       DHCPv6-IAID . . . . . . . . . . . : 722075687
       DHCPv6-Client-DUID. . . . . . . . : 00-01-00-01-1E-FA-29-B0-C8-5B-76-20-29-F1
       DNS-Server  . . . . . . . . . . . : fec0:0:0:ffff::1%1
                                           fec0:0:0:ffff::2%1
                                           fec0:0:0:ffff::3%1
       NetBIOS über TCP/IP . . . . . . . : Aktiviert
    
    Tunneladapter isatap.{67863029-37B5-4475-A830-A99108B681D0}:
    
       Medienstatus. . . . . . . . . . . : Medium getrennt
       Verbindungsspezifisches DNS-Suffix: 
       Beschreibung. . . . . . . . . . . : Microsoft-ISATAP-Adapter
       Physikalische Adresse . . . . . . : 00-00-00-00-00-00-00-E0
       DHCP aktiviert. . . . . . . . . . : Nein
       Autokonfiguration aktiviert . . . : Ja
    
    Tunneladapter isatap.{A1E35624-27B8-44CD-9F90-33505222FDC5}:
    
       Medienstatus. . . . . . . . . . . : Medium getrennt
       Verbindungsspezifisches DNS-Suffix: 
       Beschreibung. . . . . . . . . . . : Microsoft-ISATAP-Adapter #4
       Physikalische Adresse . . . . . . : 00-00-00-00-00-00-00-E0
       DHCP aktiviert. . . . . . . . . . : Nein
       Autokonfiguration aktiviert . . . : Ja
    
    Tunneladapter isatap.wifirst.net:
    
       Medienstatus. . . . . . . . . . . : Medium getrennt
       Verbindungsspezifisches DNS-Suffix: 
       Beschreibung. . . . . . . . . . . : Microsoft-ISATAP-Adapter #5
       Physikalische Adresse . . . . . . : 00-00-00-00-00-00-00-E0
       DHCP aktiviert. . . . . . . . . . : Nein
       Autokonfiguration aktiviert . . . : Ja
    
    Tunneladapter Teredo Tunneling Pseudo-Interface:
    
       Medienstatus. . . . . . . . . . . : Medium getrennt
       Verbindungsspezifisches DNS-Suffix: 
       Beschreibung. . . . . . . . . . . : Teredo Tunneling Pseudo-Interface
       Physikalische Adresse . . . . . . : 00-00-00-00-00-00-00-E0
       DHCP aktiviert. . . . . . . . . . : Nein
       Autokonfiguration aktiviert . . . : Ja
    
    Tunneladapter isatap.{8258A81F-8BED-473D-ACFA-857BDD793251}:
    
       Medienstatus. . . . . . . . . . . : Medium getrennt
       Verbindungsspezifisches DNS-Suffix: 
       Beschreibung. . . . . . . . . . . : Microsoft-ISATAP-Adapter #6
       Physikalische Adresse . . . . . . : 00-00-00-00-00-00-00-E0
       DHCP aktiviert. . . . . . . . . . : Nein
       Autokonfiguration aktiviert . . . : Ja
    
    Tunneladapter isatap.{EE03459F-FD31-4BF4-BF7E-7F3404F963B7}:
    
       Medienstatus. . . . . . . . . . . : Medium getrennt
       Verbindungsspezifisches DNS-Suffix: 
       Beschreibung. . . . . . . . . . . : Microsoft-ISATAP-Adapter #7
       Physikalische Adresse . . . . . . : 00-00-00-00-00-00-00-E0
       DHCP aktiviert. . . . . . . . . . : Nein
       Autokonfiguration aktiviert . . . : Ja
    
    Tunneladapter isatap.{5B651A37-F0DB-42B2-8109-C81D8A905622}:
    
       Medienstatus. . . . . . . . . . . : Medium getrennt
       Verbindungsspezifisches DNS-Suffix: 
       Beschreibung. . . . . . . . . . . : Microsoft-ISATAP-Adapter #8
       Physikalische Adresse . . . . . . : 00-00-00-00-00-00-00-E0
       DHCP aktiviert. . . . . . . . . . : Nein
       Autokonfiguration aktiviert . . . : Ja
    

  • Lifetime Qt Champion

    Update: filtering the addresses starting with "169.254" did not help. It now stucks three seconds on my primary "192.168.16.56" IP address.

    Thanks also @J-Hilk, the order does not seem to matter...


  • Qt Champions 2017

    How about checking directly with calls like socket(...) & bind(..) call without using Qt ?


  • Qt Champions 2017

    Any reason you are calling bind(..) each time for each interfaces ? You can also try simple with passing QHostAddress::AnyIPv4 with just one bind call. This will allows the packet to coming from any interface.


  • Lifetime Qt Champion

    @dheerendra

    How about checking directly with calls like socket(...) & bind(..) call without using Qt ?

    Have not tried yet, and probably will not have time for that soon.

    Any reason you are calling bind(..) each time for each interfaces ?

    Because I send a datagram on each interface and listen for answers.

    You can also try simple with passing QHostAddress::AnyIPv4 with just one bind call.

    Doesn't help. The first bind() call blocks, no matter which address is given. Even the overload that takes no parameters blocks.

    Every next bind() is very fast. I think @Christian-Ehrlicher is right that it is some kind of network timeout. Not sure if DNS is involved here, but I will check more deeply when I installed Wireshark on that machine.


  • Qt Champions 2017

    Not sure if DNS is involved here,

    DNS is not involved for bind. Only ARP can play role here. It is to get the MAC address corresponding to IP address. For the bind even this should not kick in. Even ARP will come into picture only if you start data transfer. Actually internally bind is not doing anything other than filling the Socket DataStructure with Source IP and Source Port#. If you are interested i can give you vanilla socket program to check on this.



  • @aha_1980
    You state that the first bind() is what takes the extra time. However, your debug output prints start before it does anything and then does not print anything till after the first bind() has completed, and state that must be what is taking the time.

    I think you should determine whether that time is actually during the QNetworkInterface::allAddresses() call, while it gathers all addresses. Pull that into its own variable and time just that part. Is that actually where the 3 seconds is spent?


  • Lifetime Qt Champion

    @JonB

    Please read the topic title from the beginning :)

    I think you should determine whether that time is actually during the QNetworkInterface::allAddresses() call, while it gathers all addresses. Pull that into its own variable and time just that part. Is that actually where the 3 seconds is spent?

    I already expected that comment - but it's valid. No, it's really the bind() that takes the time. I already split that up to gather the addresses and bind each interface separate in a QTimers timeout, but it does not help.

    Fact is, the first bind() takes ages and blocks the GUI.


  • Lifetime Qt Champion

    @dheerendra Yes, I'd try a vanilla program if you got one.

    I just will not get around to do this today, as I'm starting to Qt Summit in a few hours. So testing will have to wait at least until friday.


  • Qt Champions 2017

    Please share an email on the chat message. I will drop you an email with the program.


  • Lifetime Qt Champion

    Just as short interim report: A simple Windows winsock2 API program binds immediately. So it looks like I have to dig deeper, I just don't have the time for that right now. I'll come back to this problem later.

    Thanks for all your help so far.



  • @aha_1980
    Just as a short interim suggestion: As you are an expert Qt-er, if you're set up to run your program profiled would that immediately tell you where the extra time is being spent?


  • Lifetime Qt Champion

    @JonB probably. But nevertheless I'd need to dig into Qt sources. Also, this problem is one Windows (I'm not even sure if it is machine specific), and I dont have a debug/profile Qt setup there.

    Otherwise I'd not asked ;)


Log in to reply