【从零开始一步步学习VSOA开发】位置服务
创始人
2024-11-05 14:06:26

位置服务

VSOA 位置服务器提供了按服务名称查询 VSOA 服务器地址的功能,类似于 DNS 服务器,能有效简化客户端配置服务端地址的操作,并提高灵活性,为后面的故障自动迁移提供必要保证。位置模块 API 在 vsoa_position.hlibvsoa-position.so 中。

创建位置服务程序

参考 hellovsoa 工程,创建 position 工程,工程源码修改如下:

#include  #include  #include  #include  #include  #include "vsoa_position.h" #include "vsoa_platform.h"  #define MY_SERVER_ADDR                      "127.0.0.1"  #define MY_POSITION_SERVER_ADDR             "127.0.0.1" #define MY_POSITION_SERVER_PORT             (3000)  static vsoa_position_server_t *pos_serv;  static void query (void *arg, int domain, const char *query_name, vsoa_position_response_t *response) {     struct sockaddr_in res;          printf("query_name = %s\n", query_name);      if (strcmp(query_name, "echo_server") == 0) {         if (domain < 0 || domain == AF_INET) {             bzero(&res, sizeof(struct sockaddr_in));             res.sin_family      = AF_INET;             res.sin_port        = htons(4001);             res.sin_addr.s_addr = inet_addr(MY_SERVER_ADDR);             res.sin_len = sizeof(struct sockaddr_in);              vsoa_position_server_response(pos_serv, response,(struct sockaddr *)&res,sizeof(res), false);         }     } }  int main (int argc, char **argv) {     int cnt, fd;     fd_set fds;     struct sockaddr_in pos_addr;      /*      * 创建位置服务对象      */     pos_serv = vsoa_position_server_create(query, NULL);      /*      * 启动位置服务对象      */     bzero(&pos_addr, sizeof(struct sockaddr_in));     pos_addr.sin_family      = AF_INET;     pos_addr.sin_port        = htons(MY_POSITION_SERVER_PORT);     pos_addr.sin_addr.s_addr = inet_addr(MY_POSITION_SERVER_ADDR);     pos_addr.sin_len = sizeof(struct sockaddr_in);     vsoa_position_server_start(pos_serv,(struct sockaddr *)&pos_addr,sizeof(struct sockaddr_in));      /*      * 进入监听事件循环      */     while (1) {         FD_ZERO(&fds);          fd = vsoa_position_server_fd(pos_serv);         if (fd < 0) {             fprintf(stderr, "VSOA position server file error!\n");             return  (-1);         }         FD_SET(fd, &fds);         cnt = pselect(fd + 1, &fds, NULL, NULL, NULL, NULL);         if (cnt > 0) {             vsoa_position_server_input(pos_serv);         }     }      return  (0); }  

源码分析:

  1. VSOA 位置服务 API 函数更详细说明可以查看博客https://blog.csdn.net/ScilogyHunter/article/details/140817134
  2. 位置服务有一个固定框架:创建位置服务对象,启动位置服务对象,进入监听事件循环。
  3. 调用vsoa_position_server_create 函数可以创建位置服务对象,创建时位置服务回调函数和参数。
  4. 启动位置服务启动位置服务时要指定自身使用的 IP地址和端口号,被服务设备要通过该地址来获取位置服务。
  5. 待准备工作全部完成后,应当进入监听事件循环。
  6. 位置服务回调函数中根据请求的服务名称来返回服务地址。服务名称和服务地址的对应关系可静态实现,也可以编写程序动态实现,如通过查看某配置文件。

创建使用位置服务的客户端

服务端不使用位置服务,所以不需要修改源码。客户端可以直接配置服务端地址(如之前程序写的那样)也可以借助位置服务通过服务名称来自动获取服务端地址。
使用位置服务需要先配置位置服务地址,就是调用vsoa_position_server_start 函数时使用的地址,这样客户端才能先找到位置服务端,然后才能请求位置服务。配置位置服务地址有三种方式,且优先级地减,具体如下:

  1. 通过vsoa_position_lookup_server 函数直接配置,采纳数类型为struct sockaddr_in
  2. 通过环境变量VSOA_POS_SERVER 配置,参数形式如 127.0.0.1:3000
  3. 通过 /etc/vsoa.pos 配置文件配置,可以配置多个位置服务地址,每行一个,形式如 127.0.0.1 3000

如果直接指定了位置服务器,则只查询指定的服务器,如果尚未指定位置服务器地址,则先自动使用环境变量 “VSOA_POS_SERVER” 进行查询,如果未找到,则将自动使用 “/etc/vsoa.pos” 中配置的服务器信息进行查询。

参考原 client 工程,创建新工程,工程源码修改如下,重点注意 49 到 55 行代码:

#include  #include  #include  #include  #include "vsoa_client.h" #include "vsoa_position.h"  #define MY_SERVER_ADDR                      "127.0.0.1" #define MY_SERVER_PORT                      (4001) #define MY_SERVER_NAME                      "{\"name\":\"echo_server\"}" #define MY_SERVER_PASSWD                    "123456"  #define MY_POSITION_SERVER_ADDR             "127.0.0.1" #define MY_POSITION_SERVER_PORT             (3000)  static void on_command_echo (void *arg, struct vsoa_client *client, vsoa_header_t *vsoa_hdr, vsoa_payload_t *payload) {     printf("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) {     bool ret;     struct timespec timeout = {1, 0 };     vsoa_client_t *client;       /*      * 创建客户端      */     client = vsoa_client_create(NULL, NULL);     if (!client) {         fprintf(stderr, "Can not create VSOA client!\n");         return  (-1);     }      /*     * 连接服务端     */     struct sockaddr_in addr;     socklen_t serv_len = sizeof(struct sockaddr_in);     char info[256];      bzero(&addr, sizeof(struct sockaddr_in));     bzero(info, sizeof(info));      struct sockaddr_in pos_addr;     pos_addr.sin_family      = AF_INET;     pos_addr.sin_port        = htons(MY_POSITION_SERVER_PORT);     pos_addr.sin_addr.s_addr = inet_addr(MY_POSITION_SERVER_ADDR);     pos_addr.sin_len         = sizeof(struct sockaddr_in);     vsoa_position_lookup_server((struct sockaddr *)&pos_addr, serv_len);     vsoa_position_lookup(AF_INET, "echo_server",(struct sockaddr *)&addr, &serv_len, NULL, &timeout);     if (!vsoa_client_connect(client, (struct sockaddr *)&addr, sizeof(struct sockaddr_in),                              &timeout, MY_SERVER_PASSWD, info, sizeof(info))) {         vsoa_client_close(client);         fprintf(stderr, "Can not connect to VSOA server!\n");         return  (-1);     }     printf("Server (%s) connected\n", info);       /*      * 注册异步RPC请求      */     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);     ret = vsoa_client_call(client, VSOA_CLIENT_RPC_METHOD_GET, &url, &send, on_command_echo, NULL, NULL);     if (!ret) {         fprintf(stderr, "Asynchronous RPC call error (not connected to server)!\n");     }     /*     * 进入监听事件循环     */     while (1) {         int max_fd;         int cnt;         fd_set fds;          FD_ZERO(&fds);         max_fd = vsoa_client_fds(client, &fds);          cnt = pselect(max_fd + 1, &fds, NULL, NULL, &timeout, NULL);         if (cnt > 0) {             if (!vsoa_client_input_fds(client, &fds)) {                 fprintf(stderr, "Connection lost!\n");                 return  (-1);             }         }     } }  

参考原 client_auto 工程,创建新工程,工程源码修改如下,重点注意 35 行代码 和之前的区别:

#include  #include  #include  #include  #include "vsoa_client.h" #include "vsoa_cliauto.h"  #define MY_SERVER_PASSWD                    "123456"  static void on_command_echo (void *arg, struct vsoa_client *client, vsoa_header_t *vsoa_hdr, vsoa_payload_t *payload) {     printf("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) {     bool ret;     vsoa_client_t *client;     vsoa_client_auto_t *cliauto;      /*      * 创建客户端机器人      */     cliauto = vsoa_client_auto_create(NULL, NULL);     /*      * 由客户端机器人获取客户端对象      */     client  = vsoa_client_auto_handle(cliauto);      /*      * 启动客户端机器人      */     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;         }         /*          * 注册异步RPC请求          */         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);         ret = vsoa_client_call(client, VSOA_CLIENT_RPC_METHOD_GET, &url, &send, on_command_echo, NULL, NULL);         if (!ret) {             fprintf(stderr, "Asynchronous RPC call error (not connected to server)!\n");         }          sleep(1);     } }  

执行程序查看现象

将上面的位置服务程序和两个客户端程序都编译部署,并运行,运行结果如下:
服务端运行情况:
image.png
位置服务端运行情况:
image.png
客户端 1 运行情况:
image.png
客户端 2 运行情况:
image.png

相关内容

热门资讯

裸辞做“一人公司”,我后悔了 去年这个时候,一位以色列程序员正在东南亚旅行。他顺手把一个在脑子里转了很久的想法做成了产品,一个让任...
南京建成国内首个Pre-6G试... 4月21日,2026全球6G技术与产业生态大会在南京开幕。全息互动技术展台前,一名远在北京的工作人员...
超梵求职受邀参加“2025抖音... 超梵求职受邀参加“2025抖音巨量引擎成人教育行业生态大会”,探讨分享优质内容传播,服务万千学员。 ...
摩托罗拉Razr 2026(R... IT之家 4 月 22 日消息,摩托罗拉宣布新一代 Razr 折叠手机将于 4 月 29 日在美国发...
库克卸任,特纳斯领航:苹果新纪... 苹果首席执行官蒂姆·库克将卸任,硬件工程主管约翰·特纳斯将接任,苹果公司今天宣布此事。 库克将在夏季...