#1499·workflow

支持了UDP server

Author: BarenboimCreated Mar 2, 2024Updated Apr 21, 2025
Labelsenhancement

实现了简单的UDP server,用于支持单个UDP包的request,和单个或多个UDP 包的response交互(多个包的回复,需要使用server任务的push接口)。可以用内置的WFDnsServer实现UDP,TCP和SSL多种传输协议的DNS服务器。PR:https://github.com/sogou/workflow/pull/1498

以下这个示例实现一个UDP协议的echo server/client,使用内置的TLVMessage来交互。

cpp
#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_UDP, host, port, 0, std::move(callback));    // 创建UDP传输的client任务
    task->set_keep_alive(60 * 1000);
    return task;
}

int main()
{
    struct WFServerParams params = SERVER_PARAMS_DEFAULT;
    params.transport_type = TT_UDP;      // 这里把server的传输协议改为UDP

    WFTLVServer server(&params, [](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;
}