Multicast Issue, possible bug?



  • Hey guys.

    I'm having some issues with multicast. I've backtraced all the way to the examples (here and here)

    It seems that I cannot set TTL before the first write to the socket. But setting it after the first write works fine. My current setup requires TTL >= 2 for the packages to be delivered, that's how I bumped into this.

    Setup: Start receiver example on PC1, start sender example on PC2. PC1 displays 'Listening for multicast messages' and PC2 displays the sender GUI.

    Test case:

    • Perform Setup (above)

    • Change the TTL box to '2'

    • Press 'Start'

    • No data is received.

    • Change TTL box to '3' then back to '2'

    • Data is received.

    So, setting TTL seems to have no effect unless there has been a single write to the socket before. This had me pulling my hair for some time. Is this a feature or a bug? Or am I simply missing something?

    EDIT: PC1 (Receiver) uses Qt 5.7 on Windows 10 64b it. PC2 (Sender) uses Qt 5.3.2 on debian 64 bit inside a virtual machine.



  • replacing

    udpSocket = new QUdpSocket(this);
    

    with

    udpSocket = new QUdpSocket(this);
    udpSocket->writeDatagram(QByteArray(), QHostAddress(), 0)
    

    in the sender constructor is a workaround. But it's ugly as hell :-)


  • Qt Champions 2016

    Could you try setting it to a TCP socket?



  • I don't have time for it right now. Performing the dummy-write will have to do for now :/


  • Qt Champions 2016

    My suspicion was that the UDP socket might not be bound yet at the moment you set the TTL. When you return to the issue, do let us know how it turned out.



  • @kshegunov said in Multicast Issue, possible bug?:

    Could you try setting it to a TCP socket?

    For multicast you have to stick to UDP...


  • Qt Champions 2016

    @JohanSolo said in Multicast Issue, possible bug?:

    For multicast you have to stick to UDP...

    I know that, I meant for any regular TCP socket connection.



  • How to set TTL on a tcp socket, though?



  • @BjornW said in Multicast Issue, possible bug?:

    How to set TTL on a tcp socket, though?

    On linux use setsockopt and setsockopt on windows. The option name is IP_MULTICAST_TTL on both platforms



  • Remember that this is the Qt forums :D. I'm dealing with QTcpSocket/QUdpSocket

    I do set set QAbstractSocket::MulticastTtlOption (Which should correspond to IP_MULTICAST_TTL). But I don't see whats that does for a TCP socket.

    QAbstractSocket::MulticastTtlOption - Set this to an integer value to set IP_MULTICAST_TTL (TTL for multicast datagrams) socket option.
    


  • @BjornW said in Multicast Issue, possible bug?:

    Remember that this is the Qt forums :D. I'm dealing with QTcpSocket/QUdpSocket

    My bad... sorry!

    According to wikipedia, TTL for UDP and TCP simply defines the number of subnets the packet is allowed to travel through: "The TTL field is set by the sender of the datagram, and reduced by every router on the route to its destination. If the TTL field reaches zero before the datagram arrives at its destination, then the datagram is discarded and an ICMP error datagram (11 - Time Exceeded) is sent back to the sender."



  • Yes that is correct. The issue is that the following does not work when TTL >= 2 is needed:

    udpSocket = new QUdpSocket(this);
    udpSocket->setSocketOption(QAbstractSocket::MulticastTtlOption, 2)
    udpSocket->writeDatagram(someData, someAddress, somePort)
    

    but the following DOES work:

    udpSocket = new QUdpSocket(this);
    udpSocket->writeDatagram(QByteArray(), QHostAddress(), 0)
    udpSocket->setSocketOption(QAbstractSocket::MulticastTtlOption, 2)
    udpSocket->writeDatagram(someData, someAddress, somePort)
    

    Seems unintended.


  • Qt Champions 2016

    @BjornW said in Multicast Issue, possible bug?:

    udpSocket = new QUdpSocket(this);
    udpSocket->setSocketOption(QAbstractSocket::MulticastTtlOption, 2)
    udpSocket->writeDatagram(someData, someAddress, somePort)
    

    As I noted you should try binding the socket first. I.e. call bind() after the constructor. E.g.

    udpSocket = new QUdpSocket(this);
    udpSocket->bind();
    udpSocket->setSocketOption(QAbstractSocket::MulticastTtlOption, 2);
    

    My suspicion is that this call fails silently if you don't. Sending an empty datagram should call bind() and initialize the socket for you, but I can't see the flags applied in the deferred initialization code, namely here.



  • I will try that when I get back home.

    I was under the impression that bind() is used when listening to a socket, but then I'm relatively new to network programming.

    The multicast sender example does not use bind.

    From the docs

    For UDP sockets, after binding, the signal QUdpSocket::readyRead() is emitted whenever a UDP datagram arrives on the specified address and port. Thus, This function is useful to write UDP servers. 
    

    No mention that it is required for sending or a client.


  • Qt Champions 2016

    @BjornW said in Multicast Issue, possible bug?:

    I was under the impression that bind() is used when listening to a socket, but then I'm relatively new to network programming.
    The multicast sender example does not use bind.

    No, bind is needed. In any case writeDatagram() will bind the socket for you (internally). The problem I see is that Qt's code doesn't apply the flags after the socket is initialized. I may be completely off, but I'd say it's a minor bug. On a related note, does the example code set the TTL properly, as I really don't see any significant difference from your code?



  • @kshegunov

    I'll describe what happens in my original test case

    • Start the applications // <-- No 'bind' is called anywhere in the sender code
    • Change the TTL box to '2' //<-- the ttlChanged slot is invoked where udpSocket->setSocketOption(QAbstractSocket::MulticastTtlOption, 2); is called.
    • Press 'Start'
    • Data i sent but no data is received //<-- Because 1: My system setup requires TTL >= 2 for data to reach destination and 2: the previous setting of MulticastTtlOption has not been applied properly
    • Change TTL box to '3' then back to '2' // <-- once again, the ttlChanged slot is invoked and the setSocketOption method is called. This time, writeDatagram has been called multiple times already (implicitly calling bind()?)
    • Data is sent and is now also received properly


  • My guess is that the socket uses implicit binding, which is a current way to proceed. But I would expect udpSocket->setSocketOption to return an error "invalid socket" or something approaching.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.