飞道的博客

客户端服务端交互实现

274人阅读  评论(0)

问题

客户端业务逻辑如何实现?

与服务设备具体交互细节如何设计?

客户端业务逻辑实现

用户输入处理

  • 字符串空格处理,分割获取命令与参数

服务信息处理

  • 字符串预处理,分割获取服务命令
  • 存储服务命令与设备地址之间的映射(命令字符串 => 地址字符串)

客户端业务逻辑实现 - 用户输入处理

 

服务端逻辑实现

查询消息处理

  • 接收广播,并回复UDP消息

服务命令处理

  • 接收 TCP 连接,通过 请求-响应 的模式进行服务

UDP响应模块设计

 

服务模块设计

TCP 响应模块设计

客户端响应接收

 

客户端服务端交互实现

main.c


  
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <unistd.h>
  5. #include <sys/socket.h>
  6. #include "utility.h"
  7. #include "addr_mgr.h"
  8. #include "udp_point.h"
  9. #include "tcp_client.h"
  10. #include "type_def.h"
  11. #define BUF_SIZE 64
  12. #define DESC_SIZE 32
  13. #define ADDR_SIZE 16
  14. #define USAGE_SIZE 256
  15. #define DIM(a) sizeof((a)) / sizeof((*a))
  16. typedef struct
  17. {
  18. const char* cmd;
  19. void (*handler)( const char*);
  20. } Handler;
  21. static int GetCharCount(const char* s, int c)
  22. {
  23. int ret = 0;
  24. if(s)
  25. {
  26. while(*s)
  27. {
  28. if(*s == c)
  29. {
  30. ret++;
  31. }
  32. s++;
  33. }
  34. }
  35. return ret;
  36. }
  37. static void ParseCommand(const char* s)
  38. {
  39. const char* desc = s;
  40. const char* addr = desc + DESC_SIZE;
  41. const char* usage = addr + ADDR_SIZE;
  42. int count = 0;
  43. int cnt = 0;
  44. char** arg = NULL;
  45. char** cmd = NULL;
  46. int r = 0;
  47. printf( "desc: %s\n", desc);
  48. printf( "addr: %s\n", addr);
  49. count = GetCharCount(usage, '\n');
  50. arg = Malloc2d( char, count, BUF_SIZE);
  51. if(arg && (count > 0))
  52. {
  53. r = DivideByChar(usage, '\n', arg, count, BUF_SIZE);
  54. for( int i = 0; i < r; i++)
  55. {
  56. count = GetCharCount(arg[i], ' ') + 1;
  57. cmd = Malloc2d( char, count, BUF_SIZE);
  58. if(cmd && (count > 0))
  59. {
  60. cnt = DivideByChar(arg[i], ' ', cmd, count, BUF_SIZE);
  61. for( int j = 1; j < cnt; j++)
  62. {
  63. AddrMgr_Add(cmd[j], addr);
  64. printf( "%s %s\n", cmd[j], addr);
  65. }
  66. }
  67. Free2d(cmd);
  68. }
  69. }
  70. Free2d(arg);
  71. }
  72. void Query_Handler(const char* s)
  73. {
  74. UdpPoint* point = UdpPoint_New( 8888);
  75. Message* msg = NULL;
  76. int brd = 1;
  77. char* remote = "255.255.255.255";
  78. int port = 9999;
  79. int i = 0;
  80. if(point)
  81. {
  82. UdpPoint_SetOpt(point, SOL_SOCKET, SO_BROADCAST, &brd, sizeof(brd));
  83. msg = Message_New(TYPE_QUERY, 0, 0, 0, NULL, 0);
  84. if(msg)
  85. {
  86. UdpPoint_SendMsg(point, msg, remote, port);
  87. free(msg);
  88. msg = NULL;
  89. }
  90. while(i < 3)
  91. {
  92. if( UdpPoint_Available(point) > 0)
  93. {
  94. msg = UdpPoint_RecvMsg(point, NULL, NULL);
  95. if(msg)
  96. {
  97. if(msg->type == TYPE_RESPONSE)
  98. {
  99. printf( "Find service!\n");
  100. ParseCommand(msg->payload);
  101. i = 0;
  102. free(msg);
  103. msg = NULL;
  104. }
  105. else if(msg->type == TYPE_ERROR)
  106. {
  107. printf( "Can NOT find service!\n");
  108. }
  109. }
  110. }
  111. else
  112. {
  113. sleep( 1);
  114. i++;
  115. }
  116. }
  117. }
  118. UdpPoint_Del(point);
  119. }
  120. void Touch_Handler(const char* s)
  121. {
  122. if(s && *s)
  123. {
  124. TcpClient* client = TcpClient_New();
  125. char* addr = AddrMgr_Find(s);
  126. Message* msg = NULL;
  127. if(client && addr && TcpClient_Connect(client, addr, 8888))
  128. {
  129. msg = Message_New(TYPE_TOUCH, 0, 0, 0, s, strlen(s) + 1);
  130. if(msg)
  131. {
  132. TcpClient_SendMsg(client, msg);
  133. free(msg);
  134. msg = NULL;
  135. msg = TcpClient_RecvMsg(client);
  136. if(msg && (msg->type == TYPE_RESPONSE))
  137. {
  138. printf( "%s\n", msg->payload);
  139. free(msg);
  140. msg = NULL;
  141. }
  142. }
  143. }
  144. TcpClient_Del(client);
  145. }
  146. }
  147. Handler g_handler[] = {
  148. { "query", Query_Handler},
  149. { "touch", Touch_Handler},
  150. };
  151. int main(void)
  152. {
  153. char line[BUF_SIZE] = { 0};
  154. char** arg = NULL;
  155. int r = 0;
  156. printf( "<<<< This is client demo >>>>\n");
  157. arg = Malloc2d( char, 2, BUF_SIZE);
  158. while(arg)
  159. {
  160. fgets(line, sizeof(line), stdin);
  161. line[ strlen(line) - 1] = 0;
  162. if(*line)
  163. {
  164. r = DivideByChar(line, ' ', arg, 2, BUF_SIZE);
  165. for( int i = 0; (i < DIM(g_handler) && (r > 0)); i++)
  166. {
  167. if( strcmp(arg[ 0], g_handler[i].cmd) == 0)
  168. {
  169. g_handler[i]. handler(arg[ 1]);
  170. break;
  171. }
  172. }
  173. }
  174. }
  175. Free2d(arg);
  176. return 0;
  177. }

response_task.c


  
  1. #include <stdio.h>
  2. #include "response_task.h"
  3. #include "udp_point.h"
  4. #include "type_def.h"
  5. #define DESC_SIZE 32
  6. #define ADDR_SIZE 16
  7. #define USAGE_SIZE 256
  8. void* Response_Task(const char* arg)
  9. {
  10. UdpPoint* point = NULL;
  11. Message* msg = NULL;
  12. char remote[ 16] = { 0};
  13. int port = 0;
  14. point = UdpPoint_New( 9999);
  15. if(point)
  16. {
  17. printf( "point = 0x%X\n", point);
  18. while( 1)
  19. {
  20. msg = UdpPoint_RecvMsg(point, remote, &port);
  21. if(msg && msg->type == TYPE_QUERY)
  22. {
  23. free(msg);
  24. msg = NULL;
  25. msg = Message_New(TYPE_RESPONSE, 0, 0, 0, NULL, DESC_SIZE + ADDR_SIZE + USAGE_SIZE);
  26. if(msg)
  27. {
  28. strncpy(msg->payload, Service_GetDesc(), DESC_SIZE);
  29. strncpy(msg->payload + DESC_SIZE, Wifi_IpAddr(), ADDR_SIZE);
  30. strncpy(msg->payload + DESC_SIZE + ADDR_SIZE, Service_GetUsage(), USAGE_SIZE);
  31. UdpPoint_SendMsg(point, msg, remote, port);
  32. free(msg);
  33. msg = NULL;
  34. }
  35. else
  36. {
  37. Message m = {TYPE_ERROR};
  38. UdpPoint_SendMsg(point, &m, remote, port);
  39. }
  40. }
  41. else
  42. {
  43. Message m = {TYPE_ERROR};
  44. UdpPoint_SendMsg(point, &m, remote, port);
  45. }
  46. }
  47. UdpPoint_Del(point);
  48. }
  49. return NULL;
  50. }

local_service.h


  
  1. #ifndef LOCAL_SERVICE_H
  2. #define LOCAL_SERVICE_H
  3. typedef struct
  4. {
  5. float illumination;
  6. float humidity;
  7. float temperature;
  8. int light;
  9. } SvrData;
  10. void Service_Init(void);
  11. const char* Service_GetDesc(void);
  12. const char* Service_GetUsage(void);
  13. SvrData Service_GetData(void);
  14. int Service_SetLight(int on);
  15. #endif

local_service.c


  
  1. #include "local_service.h"
  2. void Service_Init(void)
  3. {
  4. }
  5. const char* Service_GetDesc(void)
  6. {
  7. return "Environment Service";
  8. }
  9. const char* Service_GetUsage(void)
  10. {
  11. return "Illumination: Ill_Get\n"
  12. "Temperature: Tem_Get\n"
  13. "Humidity: Hum_Get\n"
  14. "Light: Lig_Get Lig_Set_On Lig_Set_Off\n";
  15. }
  16. SvrData Service_GetData(void)
  17. {
  18. SvrData ret = { 188, 0.33, 35.6, 1};
  19. return ret;
  20. }
  21. int Service_SetLight(int on)
  22. {
  23. int ret = 1;
  24. printf( "set light: %d\n", on);
  25. return ret;
  26. }

service_task.c


  
  1. #include <stdio.h>
  2. #include "stdlib.h"
  3. #include <string.h>
  4. #include "service_task.h"
  5. #include "tcp_client.h"
  6. #include "tcp_server.h"
  7. #include "local_service.h"
  8. #include "type_def.h"
  9. typedef struct
  10. {
  11. const char* cmd;
  12. void* data;
  13. char* (*handler)( void*);
  14. } Handler;
  15. static char* FormatNumber(float num)
  16. {
  17. char* ret = ( char*) malloc( 16);
  18. snprintf(ret, 16, "%.2f", num);
  19. return ret;
  20. }
  21. static char* Ill_Get_Handler(void* data)
  22. {
  23. return FormatNumber( Service_GetData().illumination);
  24. }
  25. static char* Tem_Get_Handler(void* data)
  26. {
  27. return FormatNumber( Service_GetData().temperature);
  28. }
  29. static char* Hum_Get_Handler(void* data)
  30. {
  31. return FormatNumber( Service_GetData().humidity);
  32. }
  33. static char* Lig_Get_Handler(void* data)
  34. {
  35. char* ret = ( char*) malloc( 4);
  36. if( Service_GetData().light)
  37. {
  38. strcpy(ret, "on");
  39. }
  40. else
  41. {
  42. strcpy(ret, "off");
  43. }
  44. return ret;
  45. }
  46. static char* Lig_Set_Handler(void* data)
  47. {
  48. char* ret = ( char*) malloc( 4);
  49. Service_SetLight(( int)data);
  50. if(data)
  51. {
  52. strcpy(ret, "on");
  53. }
  54. else
  55. {
  56. strcpy(ret, "off");
  57. }
  58. return ret;
  59. }
  60. static Handler g_handler[] =
  61. {
  62. { "Ill_Get", NULL, Ill_Get_Handler},
  63. { "Tem_Get", NULL, Tem_Get_Handler},
  64. { "Hum_Get", NULL, Hum_Get_Handler},
  65. { "Lig_Get", NULL, Lig_Get_Handler},
  66. { "Lig_Set_On", ( void*) 1, Lig_Set_Handler},
  67. { "Lig_Set_Off", ( void*) 0, Lig_Set_Handler},
  68. };
  69. static int g_handler_size = sizeof(g_handler) / sizeof(*g_handler);
  70. static void Server_Listener_Handler(TcpClient* client, int evt)
  71. {
  72. if(evt == EVT_COON)
  73. {
  74. printf( "a client connect\n");
  75. }
  76. else if(evt == EVT_DATA)
  77. {
  78. Message* msg = NULL;
  79. char* s = NULL;
  80. msg = TcpClient_RecvMsg(client);
  81. if(msg && (msg->type == TYPE_TOUCH))
  82. {
  83. printf( "service type = %s\n", msg->payload);
  84. for( int i = 0; i < g_handler_size; i++)
  85. {
  86. if( strcmp(msg->payload, g_handler[i].cmd) == 0)
  87. {
  88. s = g_handler[i]. handler(g_handler[i].data);
  89. break;
  90. }
  91. }
  92. free(msg);
  93. msg = NULL;
  94. if(s)
  95. {
  96. msg = Message_New(TYPE_RESPONSE, 0, 0, 0, s, strlen(s) + 1);
  97. free(s);
  98. if(msg)
  99. {
  100. TcpClient_SendMsg(client, msg);
  101. free(msg);
  102. }
  103. else
  104. {
  105. Message m = {TYPE_ERROR};
  106. TcpClient_SendMsg(client, &m);
  107. }
  108. free(s);
  109. }
  110. }
  111. else
  112. {
  113. const char* message = "Invalid touch request";
  114. free(msg);
  115. msg = Message_New(TYPE_RESPONSE, 0, 0, 0, message, strlen(message) + 1);
  116. TcpClient_SendMsg(client, &m);
  117. }
  118. }
  119. else if(evt == EVT_CLOSE)
  120. {
  121. printf( "a client left\n");
  122. }
  123. return NULL;
  124. }
  125. void* Service_Task(const char* arg)
  126. {
  127. TcpServer* server = NULL;
  128. server = TcpServer_New();
  129. if(server)
  130. {
  131. printf( "server = 0x%X\n", server);
  132. Service_Init();
  133. TcpServer_SetListener(server, Server_Listener_Handler);
  134. TcpServer_Start(server, 8888, 5);
  135. TcpServer_DoWork(server);
  136. TcpServer_Del(server);
  137. }
  138. return NULL;
  139. }

实验结果如下图所示

 

课后思考

服务模块如何获取真实环境信息?


转载:https://blog.csdn.net/qq_52484093/article/details/128429161
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场