服务端开发
本节内容介绍 QVSOA 服务端使用 RPC 的方法。
开发须知
微服务对外提供 RPC 服务时,需要指定该 RPC 的 URL 资源标识并将该 URL 加入监听。QVSOA 提供了 QVsoaRPCServerListener
监听 RPC 请求。
开发示例
例如将“灯光状态”定义为一个 /light
的 URL 资源标识,供调用 RPC 的客户端获取灯光状态。
创建一个 RPC 监听器,当客户端调用 /light
时 QVsoaRPCServerListener
或其子类将感知到 RPC 调用并执行用户代码。具体代码示例如下:
#include <QCoreApplication>
#include <QDebug>
#include <QJsonDocument>
#include <QJsonObject>
#include <QVsoa>
#include <QProcessEnvironment>
constexpr char SERVER_INFO[] = "{\"name\":\"light_server\"}";
constexpr char SERVER_PASSWORD[] = "123456";
constexpr char SERVER_ADDR[] = "0.0.0.0";
constexpr int SERVER_PORT = 3001;
void onNewClient(QPointer<QVsoaCliHandle> client)
{
qDebug() << QStringLiteral("New client, address: %1:%2").arg(client->address().ip()).arg(client->address().port());
}
void onDisconnected(QPointer<QVsoaCliHandle> client)
{
qDebug() << QStringLiteral("Client disconnect: %1:%2").arg(client->address().ip()).arg(client->address().port());
}
class LightListener : public QVsoaRPCServerListener
{
Q_OBJECT
public:
enum LightState {
ON = 1,
OFF = 0
};
LightListener(QObject *parent = nullptr)
: QVsoaRPCServerListener("/light", parent)
{}
protected:
void onRPCCall(QPointer<QVsoaCliHandle> client,
const QVsoaHeader &header,
const QString &,
const QVsoaPayload &payload) override
{
if (header.flags() & FlagCode::FLAG_SET) {
auto doc = QJsonDocument::fromJson(payload.param().toUtf8());
auto object = doc.object();
m_lightState = static_cast<LightState>(object["light"].toInt());
}
QJsonObject obj;
obj["light"] = static_cast<int>(m_lightState);
QJsonDocument doc(obj);
client->reply(StatusCode::SUCCESS, header.seqno(), QVsoaPayload(QString::fromUtf8(doc.toJson()), {}));
}
private:
LightState m_lightState = LightState::OFF;
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
// Initialize server
QVsoaServer server(SERVER_INFO);
if (server.isInvalid()) {
qDebug() << "Can not create VSOA server!";
return -1;
}
// If need password
server.setPassword(SERVER_PASSWORD);
QObject::connect(&server, &QVsoaServer::newClient, onNewClient);
QObject::connect(&server, &QVsoaServer::clientDisconnect, onDisconnected);
// Add /light listener
LightListener listener;
listener.listen(&server);
int port = SERVER_PORT;
int auto_port = QProcessEnvironment::systemEnvironment().value("VSOA_AUTO_PORT", "-1").toInt();
if (auto_port != -1) {
port = auto_port;
}
// Start server
if (!server.start(QVsoaSocketAddress(AF_INET, SERVER_ADDR, port))) {
qDebug() << "Can not start VSOA server!";
return -1;
}
qDebug() << "Started VSOA server.";
return a.exec();
}