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