JSON-RPC 2.0 sobre WebSockets com Tufão + Phobos-RPC (Qt)

Sou uma pessoa que simpatiza com jogos e, ultimamente, estive trabalhando em um jogo orientado a disputas multiplayer pertencente ao gênero Bomberman. Para implementar a arquitetura de jogo sugerida pelo time de desenvolvimento, desenvolvi algumas bibliotecas auxiliares. E nesse post vou documentar como combinar as duas bibliotecas para permitir chamadas de métodos remotas (RPC).

A primeira biblioteca que desenvolvi para o projeto foi batizada de Phobos e sua única função é implementar o protocolo JSON-RPC 2.0. Meu objetivo principal durante seu desenvolvimento foi auxiliar o desenvolvimento do BlowThemAll e, assim sendo, alguns fatores, como arquitetura e documentação, foram deixados de lado. O projeto não tem página própria na internet e as “releases” do mesmo encontram-se na página de downloads do BlowThemAll.

Há um segundo projeto que iniciei, batizado de Tufão. É uma biblioteca desenvolvida em cima do Qt que possui uma API similar ao Node.js que pode ser usada para criar aplicações web. Desenvolvi esse projeto de forma bem disciplinada, me dedicando bastante, seja ao projetar sua arquitetura, seja ao escrever sua documentação, seja durante os testes, empacotamento para diferentes plataformas, preparação de uma página decente, criação de exemplos e documentação por fora… Caso queira saber mais sobre o mesmo, visite a página do projeto.

Pré-requisitos

 Esse texto assume que você está utilizando (e tem um pouco de familiaridade com) o QtCreator para gerenciar seus projetos e tem uma boa noção de orientação a objetos. Além disso, esse texto assume que você já instalou o Tufão no seu sistema.

Preparando um novo projeto

A primeira coisa a fazer, é baixar a biblioteca Phobos e seu “adapter” para o Tufão.

Então, usando o plugin do Tufão para o QtCreator, crie um novo projeto usando o template “application“.

Com o projeto criado, extraia o conteúdo dos arquivos baixados para a pasta do projeto e edite o arquivo *.pro do mesmo, de forma que as seguintes linhas sejam adicionadas:

QMAKE_CXXFLAGS += -std=c++11
include(phobos.pri)
include(phobos-tufao.pri)
view raw qmake project hosted with ❤ by GitHub

Pronto, você concluiu as etapas iniciais para trabalhar com um projeto usando JSON-RPC 2.0 em C++. A etapa seguinte dependerá se o projeto criado é o servidor ou o cliente.

Preparando um novo projeto (servidor)

Grande parte da “aplicação web” já está pronta, utilizando o “esqueleto” do projeto genérico criado pelo plugin do Tufão. As alterações que você precisa fazer se resumem a criar uma classe para tratar conexões WebSocket e uma classe Handler para ser utilizada pelo RPC.

Comece criando a classe WebServer, que deve herdar de Tufao::HttpServer e deve implementar o método protegido upgrade, que deve ficar assim:

void WebServer::upgrade(Tufao::HttpServerRequest *request,
const QByteArray &head)
{
Tufao::WebSocket *socket = new Tufao::WebSocket(this);
Handler *handler = new Handler(socket);
new JsonRpc(handler, socket, socket);
connect(socket, SIGNAL(disconnected()), socket, SLOT(deleteLater()));
socket->startServerHandshake(request, head);
}
view raw server.cpp hosted with ❤ by GitHub

Implemente a classe Handler herdando de QObject e utilizando a macro Q_INVOKABLE na frente da declaração/assinatura dos métodos que você deseja exportar para o cliente remoto.

O último passo é editar o arquivo main.cpp, para que o mesmo utilize a classe WebServer criada. Para isso, só precisa mudar o tipo da variável server dentro da função main, de Tufao::HttpServer para WebServer.

Preparando um novo projeto (cliente)

O cliente tem uma natureza bem diferente do esqueleto genérico de aplicação criado pelo plugin do Tufão e isso requer que você faça mais mudanças que no caso do servidor.

Primeiro, apague as classes (desnecessários para o projeto) NotFound e PluginReloader. Apague também o arquivo de recursos static.qrc e seu recurso associado, notfound.html.

Segundo, apague quase todo o conteúdo da função main, para que se resuma ao seguinte:

QCoreApplication a(argc, argv);
return a.exec();
view raw client.cpp hosted with ❤ by GitHub

Com isso terminaram as remoções necessários do projeto-base. Agora restam as adições, que se dividem em duas partes, relacionadas ao Tufão e relacionadas ao Phobos. Irei comentar o mínimo possível sobre o Tufão, pois o mesmo está bem documentado e torna-se desnecessário que eu faça comentários extras.

Começando pela parte do Tufão, você precisará criar um objeto da classe Tufao::WebSocket e chamar o método connectToHost. Quando o sinal connected for emitido, o objeto estará pronto para ser utilizado.

Do lado do Phobos, você precisará, assim como no servidor, de um objeto Handler, que herde da classe QObject e utilize a macro Q_INVOKABLE na frente da declaração/assinatura dos métodos que você deseja exportar para o servidor remoto (o protocolo JSON-RPC não distingue servidor de cliente e, uma vez iniciada a conexão, ambos podem realizar chamadas remotas, enquanto a camada de transporte permitir).

Invocando métodos remotos

Para chamar métodos remotos, utilize o método JsonRpc::callWith. Os dois primeiros argumentos que ele recebe lembram o método singleShot da classe QTimer, com a diferença que a macro SLOT não cerca o argumento member no método callWith. Os argumentos restantes representam, respectivamente, o nome do método remoto e seus argumentos. Exemplificando:

rpc->callWith(this, "onResult(QString)", "echo", "Hello World");
view raw peer.cpp hosted with ❤ by GitHub

Be happy

Você pode obter o código-fonte das aplicações desenvolvidas nesse texto aqui.

Tags:, ,

Comentários (with MarkDown support)