[SOLVED] QUdpSocket and SO_BROADCAST



  • I am using QUdpSocket and writing datagrams to a broadcast address. It is working fine without specifying the SO_BROADCAST socket option, and it works fine when I do. I have read that without specifying this socket option, the OS won't know if the packet is broadcast or not by just looking at the destination address, and that it needs to be set for everything to function correctly.

    But, the QAbstractSocket::SocketOption enum does not have SO_BROADCAST available. Is this because the resources I'm reading that tell me I have to set it are old and it is no longer necessary? Does Qt somehow do it automatically behind the scenes?

    I would really like to use only Qt code and not have to call setsockopt if possible.

    @
    //Do I need to do this?
    char opt=1;
    setsockopt(udpSocket->socketDescriptor(), SOL_SOCKET, SO_BROADCAST, &opt, sizeof(int));

    udpSocket->writeDatagram(buf, buflen, destaddr, portno); //destaddr is a broadcast address
    @

    Thanks!



  • It seems for me, what SO_BROADCAST == QHostAddress::Broadcast

    so, you don't need setscokopt, just use QHostAddress::Broadcast as destination address:
    @udpSocket->writeDatagram(buf, buflen, QHostAddress::Broadcast, portno);@



  • According to "QHostAddress documentation":http://developer.qt.nokia.com/doc/qt-4.8/qhostaddress.html#SpecialAddress-enum, that is just a default broadcast address

    bq. The IPv4 broadcast address. Equivalent to QHostAddress("255.255.255.255").

    I am already using a valid broadcast address for my IP. That is not the issue. I've tested without specifying the SO_BROADCAST option and it does work on my computer for my limited testing. I just know that there are resources that say you must specify this socket option.



  • src\network\socket\qnativesocketengine_*.cpp:
    @bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt, int v)
    {
    Q_Q(const QNativeSocketEngine);
    if (!q->isValid())
    return false;

    int n = 0;
    int level = SOL_SOCKET; // default
    
    switch (opt) {
    case QNativeSocketEngine::ReceiveBufferSocketOption:
        n = SO_RCVBUF;
        break;
    case QNativeSocketEngine::SendBufferSocketOption:
        n = SO_SNDBUF;
        break;
    case QNativeSocketEngine::BroadcastSocketOption:
        n = SO_BROADCAST;
        break;
    case QNativeSocketEngine::NonBlockingSocketOption:
        {
        unsigned long buf = v;
        unsigned long outBuf;
        DWORD sizeWritten = 0;
        if (::WSAIoctl(socketDescriptor, FIONBIO, &buf, sizeof(unsigned long), &outBuf, sizeof(unsigned long), &sizeWritten, 0,0) == SOCKET_ERROR) {
            WS_ERROR_DEBUG(WSAGetLastError());
            return false;
        }
        return true;
        break;
        }
    case QNativeSocketEngine::AddressReusable:
        n = SO_REUSEADDR;
        break;
    case QNativeSocketEngine::BindExclusively:
        n = SO_EXCLUSIVEADDRUSE;
        break;
    case QNativeSocketEngine::ReceiveOutOfBandData:
        n = SO_OOBINLINE;
        break;
    case QNativeSocketEngine::LowDelayOption:
        level = IPPROTO_TCP;
        n = TCP_NODELAY;
        break;
    case QNativeSocketEngine::KeepAliveOption:
        n = SO_KEEPALIVE;
        break;
    case QNativeSocketEngine::MulticastTtlOption:
    

    #ifndef QT_NO_IPV6
    if (socketProtocol == QAbstractSocket::IPv6Protocol) {
    level = IPPROTO_IPV6;
    n = IPV6_MULTICAST_HOPS;
    } else
    #endif
    {
    level = IPPROTO_IP;
    n = IP_MULTICAST_TTL;
    }
    break;
    case QNativeSocketEngine::MulticastLoopbackOption:
    #ifndef QT_NO_IPV6
    if (socketProtocol == QAbstractSocket::IPv6Protocol) {
    level = IPPROTO_IPV6;
    n = IPV6_MULTICAST_LOOP;
    } else
    #endif
    {
    level = IPPROTO_IP;
    n = IP_MULTICAST_LOOP;
    }
    break;
    }

    if (::setsockopt(socketDescriptor, level, n, (char*)&v, sizeof(v)) != 0) {
        WS_ERROR_DEBUG(WSAGetLastError());
        return false;
    }
    return true;
    

    }
    @

    It's just done for you...



  • I'm not quite sure what I'm looking at here.

    Are you saying that I should use that method to set SO_BROADCAST?

    Or are you saying that Qt does it magically behind the scenes?

    Edit:

    I just used getsockopt to check the SO_BROADCAST value before and after writing a datagram to a broadcast IP address. Before the writeDatagram call, it was 0. Then, after, it was 1. So I guess you are right and Qt does the work behind the scenes.
    @
    char optval = NULL;
    int optlen = sizeof(int);
    getsockopt( udpSocket->socketDescriptor(), SOL_SOCKET, SO_BROADCAST, &optval, &optlen ); //optval == 0
    udpSocket->writeDatagram( buf, buflen, destaddr, portno );
    getsockopt( udpSocket->socketDescriptor(), SOL_SOCKET, SO_BROADCAST, &optval, &optlen ); //optval == 1
    @

    Thanks for the help!



  • You usually need that option to teceive broadcast, not to send.

    Adrian

    [quote author="ibecker" date="1328198913"]According to "QHostAddress documentation":http://developer.qt.nokia.com/doc/qt-4.8/qhostaddress.html#SpecialAddress-enum, that is just a default broadcast address

    bq. The IPv4 broadcast address. Equivalent to QHostAddress("255.255.255.255").

    I am already using a valid broadcast address for my IP. That is not the issue. I've tested without specifying the SO_BROADCAST option and it does work on my computer for my limited testing. I just know that there are resources that say you must specify this socket option.[/quote]



  • [quote author="asergiu" date="1328206785"]You usually need that option to teceive broadcast, not to send.

    Adrian

    [/quote]

    I don't think that is true. I'm fairly certain it is the opposite. You need the option to send and not to receive. At least, that's what every single thing I've read says.



  • Sorry, Yes it is for sending broadcast. For receiving you get with all the traffic that arrives on the port you are bound to.

    Adrian


Log in to reply
 

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