Manual
do
Maker
.
com
Por algumas vezes tive que fazer um servidor XMLRPC utilizando a libMaia no Qt. É um processo consideravelmente simples, mas cada vez que o fiz, tive que relembrar alguns passos obrigatórios. Vou descrever aqui um exemplo de servidor em Qt e um client em python.
A lib pode ser baixada nesse link. Descomprima-a dentro da pasta do projeto. No nosso exemplo, XMLRPCServer. Entre no diretório e compile com os passos:
qmake
make
No arquivo .pro adicione o que estiver diferente disso:
QT += core gui network xml
TARGET = XMLRPCServer
TEMPLATE = app
SOURCES += main.cpp
mainwindow.cpp
HEADERS += mainwindow.h
FORMS += mainwindow.ui
INCLUDEPATH += /path/XMLRPCServer/libmaia
LIBS += /path/XMLRPCServer/libmaia/libmaia.a
Nesse arquivo foi necessário adicionar o xml e o network, além do path da libmaia e a lib.a. O server se comunica através de sinais. Então, deve criar slots e eles obrigatoriamente devem ser privados. Adiciono um exemplo simples (utilizando a classe default, MainWindow):
#include "maiaXmlRpcServer.h"
#include <QMap>
#include <QDebug>
private slots:
QString QuestionAnswer(QString QA);
private:
MaiaXmlRpcServer *server;`
QMap <QString,QString> answerDict;
No construtor do mainwindow.cpp primeiramente criaremos o objeto da libmaia especificando a porta a utilizar (qualquer uma que não esteja em uso por outro serviço):server = new MaiaXmlRpcServer(9876, this);
Agora, adiciona-se um método para a comunicação remota:
//server->addMethod(MetodoRemoto,objeto,SlotDoObjeto);
server->addMethod("QuestionAnswer",this,"QuestionAnswer");
Nesse caso, dizemos que quando receber um sinal QuestionAnswer deve-se chamar o slot do mesmo objeto chamado QuestionAnswer. O chamada remota não precisa necessariamente ter o mesmo nome do método local, isso foi apenas para simplificar.
Ainda no construtor, deve-se atribuir os valores do dicionário:
//Sim, ha outra maneira de faze-lo. Eu quero desse jeito, ponto.
this->answerDict["pepino"] = "legume";
this->answerDict["laranja"] = "fruta";`
A declaração desse método é bastante simples:
//o metodo recebera uma QString
QString MainWindow::QuestionAnswer(QString QA)
{
//se houver a chave no dicionario, faz um print
//do valor e o retorna ao solicitante
if (this->answerDict.contains(QA)){
qDebug() << this->answerDict.value(QA);
return this->answerDict[QA];
}
//De qualquer modo, deve-se retornar alguma coisa:
//deve-se fazer o include do QDebug.
qDebug() << "UNDEFINED!!";
return "undefined";
}
#!/usr/bin/env python
from xmlrpclib import ServerProxy, Error
import time,sys,random,datetime
//acumulador de erros
ERROS = 0
#O endereco do server deve ser passado como argumento
client = ServerProxy("http://"+sys.argv[1]+":9876/RPC2")
print client
#Criacao de um metodo para fazer as perguntas em um loop:
def perguntas(q):
resposta = client.QuestionAnswer(q)
print resposta
if (q == "pepino" and not resposta == "legume") or (q == "laranja" and not resposta == "fruta"):
ERROS += 1
for i in range(100):
perguntas("pepino")
perguntas("laranja")
time.sleep(0.02)
#Ao fim do loop, mostra o resultado do teste:
print "Erros: " + str(ERROS)
O arquivo chamei de xmlRpcClient.py e sua execução pode ser de duas maneiras:
chmod 755 xmlRpcClient.py&&./xmlRpcClient.py
python xmlRpcClient.py
Coloquei o básico para o entendimento do processo. Esse código tirei do último servidor que fiz para teste de estabilidade, onde incluí outros métodos em ambos os lados (cliente e servidor), com um print do resumo ao final. Disparando em uma rede interna 25 instâncias do client, cada uma fazendo requisição a 0.02s não houve nenhum erros, tanto no client quanto no server. O server rodou em um desktop core 2 duo 1.6GHZ com 2GB de ram, sendo que durante o processo consumiu ~50% da CPU e menos de 200MB de memória, inclusive gravando as requisições em disco, abrindo e fechando o arquivo a cada requisição (reforço que essa situação foi criada para testes).
A criação de um client também é possível, mas foi mais rápido escreve-lo para teste em python.
Concluo que a libmaia é bastante estável e confiável para a tarefa que se propõe; e recomendo!
Artigo sugerido: Conexão persistente com QTCPServer
Autor do blog "Do bit Ao Byte / Manual do Maker".
Viciado em embarcados desde 2006.
LinuxUser 158.760, desde 1997.