问题

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

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

客户端业务逻辑实现

用户输入处理

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

服务信息处理

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

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

服务端逻辑实现

查询消息处理

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

服务命令处理

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

UDP响应模块设计

服务模块设计

TCP 响应模块设计

客户端响应接收

客户端服务端交互实现

main.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include "utility.h"
#include "addr_mgr.h"
#include "udp_point.h"
#include "tcp_client.h"
#include "type_def.h"#define BUF_SIZE    64
#define DESC_SIZE    32
#define ADDR_SIZE    16
#define USAGE_SIZE   256#define DIM(a)      sizeof((a)) / sizeof((*a))typedef struct
{const char* cmd;void (*handler)(const char*);
} Handler;static int GetCharCount(const char* s, int c)
{int ret = 0;if(s){while(*s){if(*s == c){ret++;}s++;}}return ret;
}static void ParseCommand(const char* s)
{const char* desc = s;const char* addr = desc + DESC_SIZE;const char* usage = addr + ADDR_SIZE;int count = 0;int cnt = 0;char** arg = NULL;char** cmd = NULL;int r = 0;printf("desc: %s\n", desc);printf("addr: %s\n", addr);count = GetCharCount(usage, '\n');arg = Malloc2d(char, count, BUF_SIZE);if(arg && (count > 0)){r = DivideByChar(usage, '\n', arg, count, BUF_SIZE);for(int i = 0; i < r; i++){   count = GetCharCount(arg[i], ' ') + 1;cmd = Malloc2d(char, count, BUF_SIZE);if(cmd && (count > 0)){cnt = DivideByChar(arg[i], ' ', cmd, count, BUF_SIZE);for(int j = 1; j < cnt; j++){AddrMgr_Add(cmd[j], addr);printf("%s %s\n", cmd[j], addr);}}Free2d(cmd);}}Free2d(arg);
}void Query_Handler(const char* s)
{   UdpPoint* point = UdpPoint_New(8888);Message* msg = NULL;int brd = 1;char* remote = "255.255.255.255";int port = 9999;int i = 0;if(point){UdpPoint_SetOpt(point, SOL_SOCKET, SO_BROADCAST, &brd, sizeof(brd));msg = Message_New(TYPE_QUERY, 0, 0, 0, NULL, 0);if(msg){UdpPoint_SendMsg(point, msg, remote, port);free(msg);msg = NULL;}while(i < 3){if(UdpPoint_Available(point) > 0){msg = UdpPoint_RecvMsg(point, NULL, NULL);if(msg){if(msg->type == TYPE_RESPONSE){printf("Find service!\n");ParseCommand(msg->payload);i = 0;free(msg);msg = NULL;}else if(msg->type == TYPE_ERROR){printf("Can NOT find service!\n");}}}else{sleep(1);i++;}}}UdpPoint_Del(point);
}void Touch_Handler(const char* s)
{   if(s && *s){TcpClient* client = TcpClient_New();char* addr = AddrMgr_Find(s);Message* msg = NULL;if(client && addr && TcpClient_Connect(client, addr, 8888)){msg = Message_New(TYPE_TOUCH, 0, 0, 0, s, strlen(s) + 1);if(msg){TcpClient_SendMsg(client, msg);free(msg);msg = NULL;msg = TcpClient_RecvMsg(client);if(msg && (msg->type == TYPE_RESPONSE)){printf("%s\n", msg->payload);free(msg);msg = NULL;}}   }TcpClient_Del(client);}
}Handler g_handler[] = {{"query", Query_Handler}, {"touch", Touch_Handler},
};int main(void)
{char line[BUF_SIZE] = {0};char** arg = NULL;int r = 0;printf("<<<< This is client demo >>>>\n");arg = Malloc2d(char, 2, BUF_SIZE);while(arg){fgets(line, sizeof(line), stdin);line[strlen(line) - 1] = 0; if(*line){r = DivideByChar(line, ' ', arg, 2, BUF_SIZE);for(int i = 0; (i < DIM(g_handler) && (r > 0)); i++){if(strcmp(arg[0], g_handler[i].cmd) == 0){g_handler[i].handler(arg[1]);break;}}}}Free2d(arg);return 0;
}

response_task.c

#include <stdio.h>
#include "response_task.h"
#include "udp_point.h"
#include "type_def.h"#define DESC_SIZE    32
#define ADDR_SIZE    16
#define USAGE_SIZE   256void* Response_Task(const char* arg)
{UdpPoint* point = NULL;Message* msg = NULL;char remote[16] = {0};int port = 0;point = UdpPoint_New(9999);if(point){printf("point = 0x%X\n", point);while(1){msg = UdpPoint_RecvMsg(point, remote, &port);if(msg && msg->type == TYPE_QUERY){free(msg);msg = NULL;msg = Message_New(TYPE_RESPONSE, 0, 0, 0, NULL, DESC_SIZE + ADDR_SIZE + USAGE_SIZE);if(msg){strncpy(msg->payload, Service_GetDesc(), DESC_SIZE);strncpy(msg->payload + DESC_SIZE, Wifi_IpAddr(), ADDR_SIZE);strncpy(msg->payload + DESC_SIZE + ADDR_SIZE, Service_GetUsage(), USAGE_SIZE);UdpPoint_SendMsg(point, msg, remote, port);free(msg);msg = NULL;}else{Message m = {TYPE_ERROR};UdpPoint_SendMsg(point, &m, remote, port);}}else{Message m = {TYPE_ERROR};UdpPoint_SendMsg(point, &m, remote, port);}}UdpPoint_Del(point);}return NULL;
}

local_service.h

#ifndef LOCAL_SERVICE_H
#define LOCAL_SERVICE_Htypedef struct
{float    illumination;float    humidity;float    temperature;int      light;
} SvrData;void Service_Init(void);
const char* Service_GetDesc(void);
const char* Service_GetUsage(void);
SvrData Service_GetData(void);
int Service_SetLight(int on);#endif

local_service.c

#include "local_service.h"void Service_Init(void)
{}const char* Service_GetDesc(void)
{return "Environment Service";
}const char* Service_GetUsage(void)
{return "Illumination: Ill_Get\n""Temperature: Tem_Get\n""Humidity: Hum_Get\n""Light: Lig_Get Lig_Set_On Lig_Set_Off\n";
}SvrData Service_GetData(void)
{SvrData ret = {188, 0.33, 35.6, 1};return ret;
}int Service_SetLight(int on)
{int ret = 1;printf("set light: %d\n", on);return ret;
}

service_task.c

#include <stdio.h>
#include "stdlib.h"
#include <string.h>
#include "service_task.h"
#include "tcp_client.h"
#include "tcp_server.h"
#include "local_service.h"
#include "type_def.h"typedef struct
{const char* cmd;void* data;char* (*handler)(void*);
} Handler;static char* FormatNumber(float num)
{char* ret = (char*)malloc(16);snprintf(ret, 16, "%.2f", num);return ret;
}static char* Ill_Get_Handler(void* data)
{return FormatNumber(Service_GetData().illumination);
}static char* Tem_Get_Handler(void* data)
{return FormatNumber(Service_GetData().temperature);
}static char* Hum_Get_Handler(void* data)
{return FormatNumber(Service_GetData().humidity);
}static char* Lig_Get_Handler(void* data)
{char* ret = (char*)malloc(4);if(Service_GetData().light){strcpy(ret, "on");}else{strcpy(ret, "off");}return ret;
}static char* Lig_Set_Handler(void* data)
{char* ret = (char*)malloc(4);Service_SetLight((int)data);if(data){strcpy(ret, "on");}else{strcpy(ret, "off");}return ret;
}static Handler g_handler[] =
{{"Ill_Get", NULL, Ill_Get_Handler},{"Tem_Get", NULL, Tem_Get_Handler},{"Hum_Get", NULL, Hum_Get_Handler},{"Lig_Get", NULL, Lig_Get_Handler},{"Lig_Set_On", (void*)1, Lig_Set_Handler},{"Lig_Set_Off", (void*)0, Lig_Set_Handler},
};static int g_handler_size = sizeof(g_handler) / sizeof(*g_handler);static void Server_Listener_Handler(TcpClient* client, int evt)
{if(evt == EVT_COON){printf("a client connect\n");}else if(evt == EVT_DATA){Message* msg = NULL;char* s = NULL;msg = TcpClient_RecvMsg(client);if(msg && (msg->type == TYPE_TOUCH)){printf("service type = %s\n", msg->payload);for(int i = 0; i < g_handler_size; i++){if(strcmp(msg->payload, g_handler[i].cmd) == 0){s = g_handler[i].handler(g_handler[i].data);break;}}free(msg);msg = NULL;if(s){msg = Message_New(TYPE_RESPONSE, 0, 0, 0, s, strlen(s) + 1);free(s);if(msg){TcpClient_SendMsg(client, msg);free(msg);}else{Message m = {TYPE_ERROR};TcpClient_SendMsg(client, &m);}free(s);}}else{const char* message = "Invalid touch request";free(msg);msg = Message_New(TYPE_RESPONSE, 0, 0, 0, message, strlen(message) + 1);TcpClient_SendMsg(client, &m);}}else if(evt == EVT_CLOSE){printf("a client left\n");}return NULL;
}void* Service_Task(const char* arg)
{TcpServer* server = NULL;server = TcpServer_New();if(server){printf("server = 0x%X\n", server);Service_Init();TcpServer_SetListener(server, Server_Listener_Handler);TcpServer_Start(server, 8888, 5);TcpServer_DoWork(server);TcpServer_Del(server);}return NULL;
}

实验结果如下图所示

课后思考

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

客户端服务端交互实现相关推荐

  1. 实现Java Socket 客户端服务端交互实例

    SocketService.java package socket;import java.io.BufferedReader; import java.io.IOException; import ...

  2. SSO单点登录系列2:cas客户端和cas服务端交互原理动画图解,cas协议终极分析

    落雨 cas 单点登录 一.用户第一次访问web1应用. ps:上图少画了一条线,那一条线,应该再返回来一条,然后再到server端,画少了一步...谢谢提醒.而且,重定向肯定是从浏览器过去的.我写的 ...

  3. 处理大并发之一 对epoll的理解,epoll客户端服务端代码

    http://blog.csdn.net/zhuxiaoping54532/article/details/56494313 处理大并发之一 对epoll的理解,epoll客户端服务端代码 序言: 该 ...

  4. IPAD移动端交互原型通用设计方案、ipad元件库、移动元件库、元件列表、设计元件、交互示例、界面模板、设备模板、手势图标、社交界面、音乐、电商、视图控制器、指示器、指纹解锁、手势解锁、rp元件库

    IPAD移动端交互原型通用设计方案.ipad元件库.移动元件库.元件列表.设计元件.交互示例.界面模板.设备模板.手势图标.社交界面.音乐.电商.视图控制器.指示器.指纹解锁.手势解锁.rp元件库.平 ...

  5. web电商系统、电商平台WEB端交互原型模板、用户中心、会员中心、优惠券、积分、互动社区、运营推广、内容推荐、商品展示、订单流程、订单管理、售后及服务、Axure原型、rp原型、电商原型、商城系统原型

    作品介绍:web电商系统.电商平台WEB端交互原型模板.用户中心.会员中心.优惠券.积分.互动社区.运营推广.内容推荐.商品展示.订单流程.订单管理.售后及服务等完整的电商体系功能架构和业务流程 Ax ...

  6. Axure经典案例下载(crm需求文档+web端交互组件+Axure移动端模板+管理后台框架模板)

    crm需求文档+web端交互组件+Axure移动端模板+管理后台框架模板 作品展示2 作品展示3 作品展示4 交互演示地址及下载链接 https://www.pmdaniu.com/storages/ ...

  7. Axure手机移动端交互原型通用元件库

    点此下载全部资源 这套全新的作品在移动端元件库v1.0的基础上优化而来的,新版本正式命名为:AxureUX手机移动端交互原型通用元件库.新作品不仅对旧版本中全部的元件进行了重新整理和设计,而且还整合了 ...

  8. 基于Java的Minecraft游戏后端自定义插件 01客户端服务端

    客户端服务端 课程大纲 初识客户端与服务端 服务端 客户端 客户端下载与启动 客户端文件目录介绍 服务端与启动 服务端目录 服务端文件详解 常规游戏通信同步 课程大纲 常见服务端简介 服务端目录结构介 ...

  9. 【Python爬虫实战】用urllib与服务端交互(发送和接收数据)

    本文节选自<Python爬虫技术:深入理解原理.技术与开发>. urllib是Python3中内置的HTTP请求库,不需要单独安装,官方文档链接如下: https://docs.pytho ...

最新文章

  1. python 语言教程(3)变量之列表(List)
  2. 【分析】在线交易开启跨境电商B2B新纪元
  3. s5p4418 Android 4.4.2 驱动层 HAL层 服务层 应用层 开发流程记录(二 硬件抽象层HAL 第二种 ioctl操作方法)
  4. c不是面向对象编程语言 所以不具有面对,go 学习笔记之go是不是面向对象语言是否支持面对对象编程?...
  5. linux将什么定向到文件,linux – 将输出重定向到C中的文件
  6. linux主机中util啥意思,util-linux是什么软件
  7. Python 学习记录(1)对象命名导致的问题
  8. Nerd的套现ATM机
  9. Kafka从上手到实践 - 实践真知:Kafka Java Consumer | 凌云时刻
  10. 计算机高效课堂建设,基于信息技术的小学音乐高效课堂的构建
  11. 一般描绘性形容词_英语中描绘性形容词是指哪种形容词?
  12. 包政讲营销录音(1)
  13. 如何使用CorelDRAW 2019快速制作幻影图像效果
  14. python 爬虫程序详解
  15. 7 SY Vue 原理 副本 页面编辑错误
  16. 论中国足球教练排名,“神奇教练”米卢说第二,没人敢称第一
  17. S270无线物联网数据监测4G RTU功能介绍
  18. 华强北再也没法生产散装 iPhone 了
  19. 2020牛客暑期多校训练营(第八场) Enigmatic Partition
  20. PM-127 网关的应用

热门文章

  1. Java工程师(面试)
  2. 【Java】Java绘制UML图
  3. linux下定时清理日志任务
  4. idea debug图解
  5. 两个处理IP好用的Python库ipaddr和netaddr
  6. 7.5ElGamal算法
  7. 京东风控团队带你全方位解读特征工程
  8. 第一个HTML页面如何写?—零基础自学网页制作
  9. 有关FLOPS的定义与计算
  10. 简单的java程序代码?