服务设备软件架构设计

代码复用
将网络通信框架移植到开发板,之后,可以使用框架中的组件实现 Response Task 和 Service Task。
框架移植注意事项
LWIP 是微型 TCP/IP 协议栈 (并非完整 TCP/IP 协议栈)
支持 socket 接口,但一些功能未实现
socket 接口所在头文件不同于 Linux 和 Windows 平台
完成可移植性测试,对测试中出现的问题及时修复
可移植性测试
通过网络调试助手验证 TCP 数据收发
- 设备端运行服务端,客户端连接,数据收发功能
通过网络调试助手验证 UDP 数据收发
- 设备接收广播,并回复数据
Service Task 关键实现

Response Task 关键实现

网络通信框架移植
main_entry.c
#include <stdio.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "wifi_connect.h"
#include "response_task.h"
#include "service_task.h"
 
static void* Task_Init(const char* arg)
{
	Wifi_Init();
    Wifi_Connect("wifi_test", "12345678");
    Wifi_Start();
 
    if(Wifi_IsOk)
    {
        osThreadAttr_t attr = {0};
        printf("connect wifi success! ip = %s\n", Wifi_IpAddr());
 
        attr.name = "Response Task";
        attr.stack_size = 4 * 1024;
        attr.priority = 20;
        if(osThreadNew((osThreadFunc_t)Response_Task, NULL, &attr) == NULL)
        {
            printf("failed to create response task!\n");
        }
        attr.name = "Service Task";
        attr.stack_size = 4 * 1024;
        attr.priority = 20;
        if(osThreadNew((osThreadFunc_t)Service_Task, NULL, &attr) == NULL)
        {
            printf("failed to create service task!\n");
        }
    }
	
	return arg;
}
 
static void Main_Entry(void)
{
    osThreadAttr_t attr = {0};
 
    attr.name = "Task_Iniit";
    attr.stack_size = 4 * 1024;
    attr.priority = 20;
 
    if(osThreadNew((osThreadFunc_t)Task_Init, NULL, &attr) == NULL)
	{
		printf("failed to create task!\n");
	}
}
 
SYS_RUN(Main_Entry);response_task.h
#ifndef RESPONSE_TASK
#define RESPONSE_TASK
void* Response_Task(const char* arg);
#endifresponse_task.c
#include <stdio.h>
#include "response_task.h"
#include "udp_point.h"
void* 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 != NULL)
            {
                printf("msg = 0x%X\n", msg);
                printf("receive a message, ip = %s, port = %d\n", remote, port);
                printf("type = %d, cmd = %d, index = %d, total = %d, lengh = %d\n", msg->type, msg->cmd,msg->index, msg->total, msg->length);
                if(msg->length > 0)
                {
                    printf("data: %s\n", msg->payload);
                }
                free(msg);
            }
        }
        UdpPoint_Del(point);
    }
    return NULL;
}service_task.h
#ifndef SERVICE_TASK_H
#define SERVICE_TASK_H
void* Service_Task(const char* arg);
#endifservice_task.c
#include <stdio.h>
#include "service_task.h"
#include "tcp_server.h"
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;
        msg = TcpClient_RecvMsg(client);
        if(msg)
        {
            printf("msg = 0x%X\n", msg);
            printf("type = %d, cmd = %d, index = %d, total = %d, lengh = %d\n", msg->type, msg->cmd,msg->index, msg->total, msg->length);
            if(msg->length > 0)
            {
                printf("data: %s\n", msg->payload);
            }
            free(msg);
        }
    }
    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);
        TcpServer_SetListener(server, Server_Listener_Handler);
        TcpServer_Start(server, 8888, 5);
        TcpServer_DoWork(server);
        TcpServer_Del(server);
    }
    return NULL;
}问题及原因
LWIP 未实现选项组合 IPPORTO_TCP,TCP_INFO
int TcpClient_IsValid(TcpClient* client); 总是返回假,导致服务端逻辑错误
MParser 从内存解析数据且内存中的协议消息无 payload (length == 0)
Mparser 无法将解析状态推到最终态,导致解析结果为 NULL
实验结果

我们使用 UdpPoint 能够成功地收发数据
 
 
TCP 通信框架我们也成功的移植了过来,测试了并没有问题。
课后思考
Response Task 和 Service Task 的业务逻辑如何实现?客户端如何实现?



















