Publicado em Exemplos Qt, Programação, redes

Entradas e saídas de dados – streaming – C++/Qt – Exemplo 07

O protocolo UDP( User Datagram Protocol ) caracteriza-se essencialmente pelo facto de o emissor não necessitar de estabelecer uma ligação com os nós com que pretende comunicar ( connectionless oriented), bem como pela troca de dados ser realizada na forma de datagramas.

Por esta razão, se nada mais for feito, após o envio de um datagramas não existem garantia de que este foi entregue no(s) destinatários.

Por outro lado é muito leve e de utilização relativamente simples, pelo que serve perfeitamente para o exemplo que aqui pretendo mostrar.

O Qt disponibiliza a classe QUdpSocket que implementa o protocolo de transporte UDP.

Tratando-se de uma classe derivada de QIODevice, que como já vimos pode ser manipulada recorrendo a objectos instanciados a partir das classe QTextStrem e QDataStream, vamos precisamente tirar partido deste facto para trocarmos os nossos datagramas.

A ideia é criar duas aplicações: Sender e Receiver.

sender

receiver

O Sender permite mudar a luz de um semáforo e os postos da rede que estiverem a executar o receiver reflectem essa alteração, ligando a luz correspondente.

O modo de comunicação será broadcast e a porta utilizada é a 45454 .

Os exemplos em que me baseei foram os seguintes:

download

Algumas notas:

  • É necessário incluir “QT += network” no ficheiro .pro, pois só assim será feita a “linkagem” ao módulo Qt Network. Caso criem o projecto no Qt Creator este já trata do assunto, mas convém não esquecer de seleccionar este módulo.
  • Caso o datagrama não seja entregue com sucesso, nenhuma mensagem de erro será enviada ao emissor, ou seja, este não tem garantias nenhumas que o semáforo mudou de cor. O erro vai acontecer facilmente numa rede congestionada.
  • Como não estamos a ler os dados a partir de um ficheiro no disco, é necessário garantir que todos os datagramas são recebidos antes de passar a informação ao stream.
...
    QByteArray datagram;

    do {
        datagram.resize(udpSocket->pendingDatagramSize());
        udpSocket->readDatagram(datagram.data(), datagram.size());
    } while (udpSocket->hasPendingDatagrams());

    int m;

    QDataStream in(&datagram, QIODevice::ReadOnly);
    in.setVersion(QDataStream::Qt_4_1);
    in >> m;    //for more data in >> m >> n >> o >> p >> ...;
...