问题:Response Task 和 Server Task 的业务逻辑如何实现?客户端如何实现?
再论交互流程
交互详细设计(Message::payload)
- 客户端主动发起服务查询(局域广播)
- 服务设备将自身能提供的服务信息及用法返回(字符串描述)
- 客户端根据收到的服务用法向设备发起请求(字符串描述)
- 服务设备接收命令并匹配服务,并返回服务结果(字符串描述)
交互示例
关键问题
"Touch Lig_On" 怎么知道给哪一个服务设备发送命令?
地址管理器模块
每个服务设备在回复服务查询信息时,会附带服务地址;因此,记录服务命令与设备地址之间存在映射关系。
#ifndef ADDR_MSG_H
#define ADDR_MSG_H
int AddrMgr_Add(const char *cmd, const char *addr);
char *AddMgr_Find(const char *cmd);
void AddMgr_Remove(const char *cmd);
void AddMgr_Clear();
#endif // ADDR_MSG_H
基础功能模块
#define Malloc2d(type, row, col) ({});
void Free2d(void *p);
char *FormatByChar(const char *src, char c);
int DivideByChar(const char *line, char c, char **argv, int row, int col);
编程实验:客户端初步实现
main.c
#include <stdio.h>
#include <string.h>
#include "utility.h"
#include "addr_mgr.h"
int main()
{
const char *src = " abc de ";
char ** argv = Malloc2d(char, 3, 5);
int r = DivideByChar(src, ' ', argv, 3, 5);
int i = 0;
for (i=0; i<r; i++) {
printf("argv[%d] = *%s*\n", i, argv[i]);
}
Freee2d(argv);
AddrMgr_Add("delpin", "1.1.1.1");
AddrMgr_Add("tang", "2.2.2.2");
AddrMgr_Add("D.T.Software", "3.3.3.3");
printf("delpin = *%s*\n", AddrMgr_Find("delpin"));
printf("tang = *%s*\n", AddrMgr_Find("tang"));
printf("D.T.Software = *%s*\n", AddrMgr_Find("D.T.Software"));
AddMgr_Clear();
return 0;
}
输出:
argv[0] = *abc*
argv[1] = *de*
delpin = *1.1.1.1*
tang = *2.2.2.2*
D.T.Software = *3.3.3.3*
utility.h
#ifndef UTILITY_H
#define UTILITY_H
#include <stdlib.h>
#define Malloc2d(type, row, col) \
({ \
type **ret = NULL; \
\
if ((row > 0) && (col > 0)) { \
type* p = NULL; \
\
ret = (type**)malloc(row * sizeof(type*)); \
p = (type*)malloc(row * col * sizeof(type)); \
\
if ((ret != NULL) && (p != NULL)) { \
int i = 0; \
for (i=0; i<row; ++i) { \
ret[i] = p + i * col; \
} \
} else { \
free(ret); \
free(p); \
} \
} \
\
ret; \
})
void Freee2d(void *p);
char *FormatByChar(const char *src, char c);
int DivideByChar(const char *line, char c, char **argv, int row, int col);
#endif // UTILITY_H
utility.c
#include "utility.h"
#include <string.h>
void Freee2d(void *p)
{
void **pp = p;
if (pp && *pp) {
free(*pp);
}
free(pp);
}
char* FormatByChar(const char* src, char c) // O(n)
{
int i = 0;
int j = 0;
int len = src ? strlen(src) : 0;
int flag = 0;
char* ret = len ? malloc(len + 1) : NULL;
if( ret )
{
while( (i < len) && (src[i] == c) ) i++;
while( i < len )
{
if( src[i] != c )
{
ret[j++] = src[i];
flag = 0;
}
else
{
if( !flag )
{
ret[j++] = src[i];
flag = 1;
}
}
i++;
}
if( flag ) j--;
ret[j] = 0;
}
return ret;
}
int DivideByChar(const char *line, char c, char **argv, int row, int col)
{
int ret = 0;
if( line && argv )
{
int i = 0;
int j = 0;
char* buf = FormatByChar(line, c);
int len = buf ? strlen(buf) : 0;
if( len )
{
buf[len] = c;
for(i=0, j=0; (i<=len) && (ret<row); i++)
{
if( buf[i] == c )
{
int k = (i-j < col) ? i-j : col;
strncpy(argv[ret], buf+j, k);
argv[ret][(k < col) ? k : (k-1)] = 0;
j = i + 1;
ret++;
}
}
free(buf);
}
}
return ret;
}
addr_mgr.h
#ifndef ADDR_MGR_H
#define ADDR_MGR_H
int AddrMgr_Add(const char *cmd, const char *addr);
char * AddrMgr_Find(const char *cmd);
void AddMgr_Remove(const char * cmd);
void AddMgr_Clear();
#endif // ADDR_MGR_H
addr_mgr.c
#include "addr_mgr.h"
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include "list.h"
#define CMD_SIZE 48
#define IP_SIZE 16
typedef struct {
struct list_head head;
char cmd[CMD_SIZE];
char ip[IP_SIZE];
}SvrAddr;
static LIST_HEAD(g_svrList);
int AddrMgr_Add(const char *cmd, const char *addr)
{
int ret = 0;
if (cmd && addr) {
char *ip = AddrMgr_Find(cmd);
if (ip) {
ret = !!strcpy(ip, addr);
} else {
SvrAddr *sa = malloc(sizeof(SvrAddr));
if (ret = !!sa) {
strncpy(sa->cmd, cmd, CMD_SIZE);
strncpy(sa->ip, addr, IP_SIZE);
sa->cmd[CMD_SIZE - 1] = 0;
sa->ip[IP_SIZE - 1] = 0;
list_add((struct list_head*)sa, &g_svrList);
}
}
}
return ret;
}
char * AddrMgr_Find(const char *cmd)
{
char *ret = NULL;
if (cmd) {
struct list_head *pos = NULL;
list_for_each(pos, &g_svrList) {
SvrAddr *c = (SvrAddr*)pos;
if (strcmp(cmd, c->cmd) == 0) {
ret = c->ip;
break;
}
}
}
return ret;
}
void AddMgr_Remove(const char * cmd)
{
char *ip = AddrMgr_Find(cmd);
if (ip) {
SvrAddr *sa = container_of(ip, SvrAddr, ip);
list_del((struct list_head*)sa);
free(sa);
}
}
void AddMgr_Clear()
{
while (!list_empty(&g_svrList)) {
struct list_head *sa = g_svrList.next;
list_del(sa);
free(sa);
}
}
课后思考
客户端业务逻辑如何实现?与服务设备具体交互细节如何设计?
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。