【从零开始一步步学习VSOA开发】VSOA数据报

发布于:2024-08-12 ⋅ 阅读:(190) ⋅ 点赞:(0)

VSOA数据报

概念

Datagram 是 VSOA 的一种数据传输类型,通常这种类型用于传输一些不需要确认的数据,例如传输视频流数据或构建 VPN 网络。

Datagram 可以简单快速的在网络中传输数据。它即不需要建立连接,也不需要维护连接,因此可以更快地传输数据。VSOA 提供了⼀套全新的、接口简洁的 Datagram,具有如下特征:

  • Datagram 对故障有较强的适应性。若某条链路发生故障,数据报可以绕过这些故障路径选择其他路径,将数据报传送到目的节点。
  • Datagram 传输不需要建立连接。目的节点接收数据报后,也不需要发送确认,通信开销较小。

客户端和服务端建立连接后,双方均可发送和接收 VSOA Datagram。发送使用直接调用函数方式;而接收使用事件机制,需要绑定一个接收回调函数。

基于数据报也可以实现类似 RPC 或发布订阅功能,RPC 或发布订阅可以绑定到了具体的 url 服务地址,而数据报只绑定到了服务端地址,业务上可以通过携带的 url 参数来自行实现子一级功能和 url 匹配关系。 RPC 或发布订阅可以建立多个,而数据报一个客户和一个服务端只能建立一个。

服务端源码

参考原 echo RPC 服务例程源码,改用 datagram 方式实现一个类似的 echo 服务。去掉 RPC 服务相关操作,注册 datagram 回调函数,回调函数中首先打印客户端和 message 信息,然后使用 datagram 方式将数据原样反射给客户端。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "vsoa_platform.h"
#include "vsoa_server.h"

#define MY_SERVER_ADDR                      "0.0.0.0"
#define MY_SERVER_PORT                      (4001)
#define MY_SERVER_NAME                      "{\"name\":\"echo_server\"}"
#define MY_SERVER_PASSWD                    "123456"

void datagram_callback(void *arg, vsoa_server_t *server, vsoa_cli_id_t cid,
                      vsoa_url_t *url, vsoa_payload_t *payload, bool quick)
{
    struct sockaddr_in addr_in;
    socklen_t          namelen = sizeof(addr_in);

    vsoa_server_cli_address(server, cid, (struct sockaddr *)&addr_in, &namelen);
    printf("datagram client %d addr is %s:%d\n", cid, inet_ntoa(addr_in.sin_addr), ntohs(addr_in.sin_port));
    printf("datagram message, url:%.*s, param:%.*s, data:%.*s\n",
           (int)url->url_len, url->url,
           (int)payload->param_len, payload->param,
           (int)payload->data_len, (char *)payload->data);

    vsoa_server_cli_datagram(server, cid, url, payload);
}

int main (int argc, char **argv)
{
    vsoa_server_t *server;

    /*
    * 创建服务端
    */
    server = vsoa_server_create(MY_SERVER_NAME);
    if (!server) {
        fprintf(stderr, "Can not create VSOA server!\n");
        return  (-1);
    }

    /*
    * 设置密码,设置为NULL,表示密码为空,客户端可以不输入密码
    */
    vsoa_server_passwd(server, MY_SERVER_PASSWD);

    /*
    * 创建RPC服务
    */
    vsoa_server_on_datagram(server, datagram_callback, NULL);

    /*
    * 启动微服务
    */
    struct sockaddr_in addr;
    bzero(&addr, sizeof(struct sockaddr_in));
    addr.sin_family      = AF_INET;
    addr.sin_port        = htons(MY_SERVER_PORT);
    addr.sin_addr.s_addr = inet_addr(MY_SERVER_ADDR);
    addr.sin_len         = sizeof(struct sockaddr_in);

    if (!vsoa_server_start(server, (struct sockaddr *)&addr, sizeof(struct sockaddr_in))) {
        vsoa_server_close(server);
        fprintf(stderr, "Can not start VSOA server!\n");
        return  (-1);
    }

    /*
    * 进入监听事件循环
    */
    while (1) {
        int     cnt;
        int     max_fd;
        fd_set  fds;
        struct timespec timeout = {1, 0 };

        FD_ZERO(&fds);
        max_fd = vsoa_server_fds(server, &fds);

        cnt = pselect(max_fd + 1, &fds, NULL, NULL, &timeout, NULL);
        if (cnt > 0) {
            vsoa_server_input_fds(server, &fds);
        }
    }

    return (0);
}

客户端源码

参考原 echo RPC 客户端例程源码,改用 datagram 方式实现一个类似的 echo 服务请求。去掉 RPC 相关操作,先注册datagram 接收回调,然后在主循环里每秒进行一次datagram 发送操作。datagram 在接收回调中打印接收信息。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/select.h>
#include "vsoa_client.h"
#include "vsoa_cliauto.h"

#define MY_SERVER_PASSWD                    "123456"

static void datagram_callback(void *arg, vsoa_client_t *client, vsoa_url_t *url,vsoa_payload_t *payload, bool quick)
{
    printf("datagram echo message, url:%.*s, quick:%s\n",
            (int)url->url_len, url->url,
            quick ? "ture":"false");

    printf("datagram echo message, param:%.*s, data:%.*s\n",
               (int)payload->param_len, payload->param,
               (int)payload->data_len, (char *)payload->data);
}

int main (int argc, char **argv)
{
    vsoa_client_t *client;
    vsoa_client_auto_t *cliauto;

    /*
     * 创建客户端机器人
     */
    cliauto = vsoa_client_auto_create(NULL, NULL);
    /*
     * 由客户端机器人获取客户端对象
     */
    client  = vsoa_client_auto_handle(cliauto);

    vsoa_client_on_datagram(client, datagram_callback, NULL);
    /*
     * 启动客户端机器人
     */
    vsoa_client_auto_start(cliauto, "vsoa://echo_server", MY_SERVER_PASSWD, NULL, 0, 1000, 1000, 1000);

    while (true) {
        /*
         * 检查客户端是否正常链接到服务端
         */
        if (vsoa_client_is_connect(client) == false) {
            continue;
        }
        /*
         * 发送datagram请求
         */
        vsoa_url_t url;
        vsoa_payload_t send;
        url.url     = "/echo";
        url.url_len = strlen(url.url);
        send.data = "1234567";
        send.data_len = strlen(send.data);
        send.param = "abcdefg";
        send.param_len = strlen(send.param);
        vsoa_client_datagram(client, &url, &send);

        sleep(1);
    }
}

执行效果

服务端执行效果:
image.png
客户端自行效果:
image.png


网站公告

今日签到

点亮在社区的每一天
去签到