同步操作将从 搜狗开源/workflow 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
A TLV message is a message consisting of type, length, and value. Because its format is simple and universal, and it is convenient for nesting and expansion, it is especially suitable for defining communication messages. To facilitate users to implement custom protocols, we have built-in support for TLV messages.
The general TLV structure does not specify the bytes of the Type or Length field. In our protocol, they occupy 4 bytes each (network order). In other words, our message has an 8-byte message header and a Value content of no more than 32GB. We do not specify the meaning of the Type and Value fields.
Because the definition of TLV format is simple. The interfaces of this TLVMessage are very simple too.
namespace protocol
{
class TLVMessage : public ProtocolMessage
{
public:
int get_type() const { return this->type; }
void set_type(int type) { this->type = type; }
std::string *get_value() { return &this->value; }
void set_value(std::string value) { this->value = std::move(value); }
protected:
int type;
std::string value;
...
};
using TLVRequest = TLVMessage;
using TLVResposne = TLVMessage;
}
If users directly use TLV messages for data transmission, they only need to use the above interfaces. Set and get Type and Value respectively. Value is directly returned as std::string
, which is convenient for users to move data directly through std::move
when necessary.
The following code directly starts a server based on TLV messages, and generates a client task through the command line for interaction.
#include <stdio.h>
#include <string>
#include <iostream>
#include "workflow/WFGlobal.h"
#include "workflow/WFFacilities.h"
#include "workflow/TLVMessage.h"
#include "workflow/WFTaskFactory.h"
#include "workflow/WFServer.h"
using namespace protocol;
using WFTLVServer = WFServer<TLVRequest, TLVResponse>;
using WFTLVTask = WFNetworkTask<TLVRequest, TLVResponse>;
using tlv_callback_t = std::function<void (WFTLVTask *)>;
WFTLVTask *create_tlv_task(const char *host, unsigned short port, tlv_callback_t callback)
{
auto *task = WFNetworkTaskFactory<TLVRequest, TLVResponse>::create_client_task(
TT_TCP, host, port, 0, std::move(callback));
task->set_keep_alive(60 * 1000);
return task;
}
int main()
{
WFTLVServer server([](WFTLVTask *task) {
*task->get_resp() = std::move(*task->get_req());
});
if (server.start(8888) != 0) {
perror("server.start");
exit(1);
}
auto&& create = [](WFRepeaterTask *)->SubTask * {
std::string string;
printf("Input string (Ctrl-D to exit): ");
std::cin >> string;
if (string.empty())
return NULL;
auto *task = create_tlv_task("127.0.0.1", 8888, [](WFTLVTask *task) {
if (task->get_state() == WFT_STATE_SUCCESS)
printf("Server Response: %s\n", task->get_resp()->get_value()->c_str());
else {
const char *str = WFGlobal::get_error_string(task->get_state(), task->get_error());
fprintf(stderr, "Error: %s\n", str);
}
});
task->get_req()->set_value(std::move(string));
return task;
};
WFFacilities::WaitGroup wait_group(1);
WFRepeaterTask *repeater = WFTaskFactory::create_repeater_task(std::move(create), nullptr);
Workflow::start_series_work(repeater, [&wait_group](const SeriesWork *) {
wait_group.done();
});
wait_group.wait();
server.stop();
return 0;
}
In the echo server example above, we directly use the original TLVMessage. However, it is suggested that in specific applications, users can derive TLVMessage. In the derived class, provide a richer interface to set and extract message content, avoid direct manipulation of the original Value field, and form its own secondary protocol. For example, if we implement a JSON protocol, we can:
#include "workflow/json-parser.h" // built-in JSON parser
class JsonMessage : public TLVMessage
{
public:
void set_json_value(const json_value_t *val)
{
this->type = JSON_TYPE;
this->json_to_string(val, &this->value); // you have to implement this function
}
json_value_t *get_json_value() const
{
if (this->type == JSON_TYPE)
return json_parser_parse(this->value.c_str()); // json-parser's interface
else
return NULL;
}
};
using JsonRequest = JsonMessage;
using JsonResponse = JsonMessage;
using JsonServer = WFServer<JsonRequest, JsonResponse>;
This example is just to illustrate the importance of derivation. In actual applications, derived classes may be far more complicated than this.
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。