《Linux网络开发必学教程》22_客户端设计与初步实现

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

再论交互流程

《Linux网络开发必学教程》22_客户端设计与初步实现_第1张图片

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

《Linux网络开发必学教程》22_客户端设计与初步实现_第2张图片

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

交互示例

《Linux网络开发必学教程》22_客户端设计与初步实现_第3张图片

关键问题

"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 
#include 

#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

输出:

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 

#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

utility.c

#include "utility.h"

#include 

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

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 
#include 
#include 

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

课后思考

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

你可能感兴趣的:(clinux网络编程)