UDP listening ports

I am trying do understand the socket level communication between PX4 and QgroundControl.
First question: Why does the PX4 bind a local port to the socket before broadcasting its heartbeat to 14550?
Second question: How does QGC catch the adress port from PX4 to answer? Because if we use bind function at PX4, QGC is obvious the client and we can’t bind a socket to a specific port to listen for connections.

Dear Stalone,
“Why does the PX4 bind a local port to the socket before broadcasting its heartbeat to 14550”.

If an application expect any incoming data on a socket, it must bind() a local port to the socket, so that sender can send the data to that port. This is what QGC does. At startup it binds local port 14550 and PX4 sends its heartbeat to port 14550. If QGC doesn’t bind a port and starting listening on that port, then PX4 has no means to communicate with QGC.

“How does QGC catch the adress port from PX4 to answer?”
When PX4 sends a heartbeat, it packs its own IP address and local listening port as part of datagram and send it to QGC. So when QGC receive a heartbeat message, it know who sent it. Then QGC replies back using the received IP address and port.

Here is a code snippet from QGC. After readDatagram() call, sender and senderPort gets populated with PX4 IP address and PX4 listening port. In future, QGC uses this sender address and sender port to communicate with PX4.

void UDPLink::readBytes()
{
    if (!_socket) {
        return;
    }
    QByteArray databuffer;
    while (_socket->hasPendingDatagrams())
    {
        QByteArray datagram;
        datagram.resize(_socket->pendingDatagramSize());
        QHostAddress sender;
        quint16 senderPort;
        //-- Note: This call is broken in Qt 5.9.3 on Windows. It always returns a blank sender and 0 for the port.
        _socket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);
        databuffer.append(datagram);
        //-- Wait a bit before sending it over
        if (databuffer.size() > 10 * 1024) {
            emit bytesReceived(this, databuffer);
            databuffer.clear();
        }

Hope it answers your question.

2 Likes

Thanks a lot. That part from QGC solved the puzzle.
I wouldn’t get there because I thought we could just bind a local port from one side (PX4 the server) instead of both sides (QGC and PX4). Can we conclude from the UDP classic architecture communication diagrams we are dealing communications between two servers?

Yes. From PX4 heartbeat point of view, QGC is the server it has to report to.

1 Like