问题:Response Task 和 Server Task 的业务逻辑如何实现?客户端如何实现?

再论交互流程

image.png

交互详细设计(Message::payload)

image.png

  • 客户端主动发起服务查询(局域广播)
  • 服务设备将自身能提供的服务信息及用法返回(字符串描述)
  • 客户端根据收到的服务用法向设备发起请求(字符串描述)
  • 服务设备接收命令并匹配服务,并返回服务结果(字符串描述)

交互示例

image.png

关键问题

"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);
    }
}

课后思考

客户端业务逻辑如何实现?与服务设备具体交互细节如何设计?

TianSong
734 声望138 粉丝

阿里山神木的种子在3000年前已经埋下,今天不过是看到当年注定的结果,为了未来的自己,今天就埋下一颗好种子吧