服务设备软件架构设计
代码复用
将网络通信框架移植到开发板,之后,可以使用框架中的组件实现 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_TASKvoid* Response_Task(const char* arg);#endif
response_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_Hvoid* Service_Task(const char* arg);#endif
service_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 的业务逻辑如何实现?客户端如何实现?