Search code examples
c++qtqt5qtcoreqtnetwork

Answer an UDP packet


I have a UDP server using the following code:

void initialize() 
{
    connect(&_udpSocket, SIGNAL(readyRead()), this, SLOT(onUdpDatagram()));

    _udpSocket.bind(QHostAddress::Any, 28283);
}

void onUdpDatagram()
{
    qDebug() << "udp packet received!";
    _udpSocket.write("Hello");
}

Unfortunately when a UDP packet is received, I have the following error in the log:

QIODevice::write: device not open

How can I make the UDP socket writable? I tried to create another socket for the answer that connect to the sender address and port but the sending won't use the 28283 port anymore...

Any idea?

For info: I'm using Qt 5.2.1 on MacOS 10.9


Solution

  • UDP is not a connection-based protocol. You don't get a separate socket for each peer, instead there's one socket for all communication on a single port.

    Therefore, there's some extra effort needed to reply to an incoming UDP packet. You need to retrieve the sender address from the datagram you received, and send back to that same address. In the sockets API this is done by using recvfrom and sendto functions instead of recv (or read) and send (or write) -- the latter are designed for connected sockets like you use with TCP.

    You didn't show the declaration (really, the type) for your _udpSocket variable, so I'm assuming that you are using a QUdpSocket. In that case, it looks like you will want to use the readDatagram and writeDatagram functions, which like recvfrom and sendto, have an additional parameter for the peer address (actually, it's a pair, one for the IP address, one for the port).

    Here's what the Qt documentation says about that:

    The most common way to use this class is to bind to an address and port using bind(), then call writeDatagram() and readDatagram() to transfer data. If you want to use the standard QIODevice functions read(), readLine(), write(), etc., you must first connect the socket directly to a peer by calling connectToHost().