我正在做一个定制板项目:
目标是获得一个固件版本,实现一个 TCP 服务器处理多个客户端连接,最多 10 个,通过相同的应用程序端口。
首先,我保留了演示项目结构(应用笔记上说这个结构是正确的方式)DemoApp_AN。然后我自定义了这个线程,添加了发送应答的操作(从服务器到客户端应用程序)。它在“服务器 - 只有一个客户端”模式下工作正常。
所以,考虑如何创建多客户端线程,我在每个新连接到达时创建了另一个线程。我按照这个方案实施:
服务器线程和客户端句柄线程实现(我的):
/**extern global**/
extern uint8_t BWR_FLAG;
extern uint8_t SWR_FLAG;
extern uint8_t tcpBufferWRL[20];
extern uint8_t tcpBufferWRS[5];
extern uint8_t enableBlink[16];
extern uint8_t BytesRD[16];
extern uint8_t Length;
extern sPins gpio_inputs[MAX_IN_PINS];
extern sPins gpio_outputs[MAX_OUT_PINS];
extern sPins gpio_adr[MAX_ADR_PINS];
struct netif gnetif;
static void tcpecho_thread(void *arg)
{
struct netconn *conn, *newconn;
err_t err, accept_err;
LWIP_UNUSED_ARG(arg);
/* Create a new connection identifier. */
conn = netconn_new(NETCONN_TCP);
if (conn!=NULL)
{
/* Bind connection to well known port number 7. */
err = netconn_bind(conn, NULL, 43808);//todo: magic number
if (err == ERR_OK)
{
/* Tell connection to go into listening mode. */
netconn_listen(conn);
while (1)
{
/* Grab new connection. */
accept_err = netconn_accept(conn, &newconn);
/* Process the new connection. */
if (accept_err == ERR_OK)
{
// new connected client thread
sys_thread_new("ActiveConn_thread", ActiveConn_thread, (void*)newconn, DEFAULT_THREAD_STACKSIZE, TCPECHO_THREAD_PRIO );
}
}
}
else
{
netconn_delete(newconn);
}
}
}
/*-----------------------------------------------------------------------------------*/
void tcpecho_init(void)
{
sys_thread_new("tcpecho_thread", tcpecho_thread, NULL, DEFAULT_THREAD_STACKSIZE, TCPECHO_THREAD_PRIO );
}
/*-----------------------------------------------------------------------------------*/
/*Here is the client thread with their actions once
packet is received up to the answer and closing connection*/
static void ActiveConn_thread(void *arg)
{
struct netconn *newconn = arg;
struct netbuf *buf;
void *data;
u16_t len;
uint8_t pp[20];
uint8_t *buffer = NULL ;
uint8_t nPin = 0;
/* get new client connection reiceved buffer */
while (netconn_recv(newconn, &buf) == ERR_OK) //buf = netbuf = packet buffer from netconn
{
do
{
netbuf_data(buf, &data, &len);//Get the data pointer and length of the data inside a netbuf = buf = paquet rebut.
buffer = (uint8_t*)data;
Length = len-1;
//*get bytes
for (uint8_t i = 0; i<=len;i++)
{
pp[i]=buffer[i];
}
if(pp[0] == 0xC1)
{
len = 16;
for (uint8_t i = 0; i<len;i++)
{
BytesRD[i] = ML_GPIO_GetState(gpio_inputs[i].tPort,gpio_inputs[i].tPin);
if (BytesRD[i] == 0) BytesRD[i] = 1;
else BytesRD[i] = 0;
}
/* answer*/
data = (void*)BytesRD;
netconn_write(newconn, data, len, NETCONN_COPY);
}
}
while (netbuf_next(buf) >= 0);
netbuf_delete(buf);
}
/* Close connection and discard connection identifier. */
netconn_close(newconn);
netconn_delete(newconn);
vTaskDelete( NULL );
}
问题:
这似乎工作正常,直到客户端数量达到 5 的值,如果第 6 个客户端尝试连接此服务器,连接就会丢失。当我断开同一个客户端时,也会发生同样的情况。当连接数达到此数量时,新线程客户端的创建将停止。因此,没有完成新的客户端连接。
所以寻找问题我调试了 LwIP 文件,我注意到这些事情:
while (netconn_recv(newconn, &buf) == ERR_OK) //buf = netbuf = packet buffer from netconn
buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);
看到,似乎内存问题是问题所在。这可能是错误的多客户端线程创建、错误的任务删除、LwIP 错误配置等的结果
所以我继续进行一些检查,发现服务器无法创建超过 6 个线程。这让我怀疑 Rtos 问题。我意识到也许我需要增加 FreeRtosconfig 文件上的内存堆。
改进尝试:
我也采取了这些行动:
我确保我启用了 freertos RAM 编写器而不是应用程序编写器。
然后我增加了堆大小,
所以在这个动作之后,服务器线程可以创建的客户端任务的数量从 5 增加到 18.
这是一个改进,但主要问题仍未解决:如果在同一个创建的线程中调用,资源释放操作似乎不适用于 terminatetask(id) 操作。我已经了解到,如果在 RTOS 配置为在 RAM 上写入 freeRtos 时调用终止函数,资源将自动释放。
问题:
如果删除任务没有释放被删除线程的内存资源,之前是否需要做其他事情?如何做呢?我要求建议或任何相关信息。
发帖:
根据评论,我尝试搜索FreeRtos中间件在我的项目中有什么样的内存管理,我看到了这个:
我猜这意味着项目正在使用 pvPortMalloc 而不是 malloc。如果我错了,请告诉我。