|
楼主 |
发表于 2021-12-18 08:52:26
|
显示全部楼层
static void tcp_recv_task(void *thread_param)
{
INT32 recved_len = 0; //已接收的长度
SOCKET_MNT *socket_mnt = &g_device.socket_mnt;
socket_mnt->recved_len = 0;
socket_mnt->recv_buf = tcp_recv_buf;
UINT8 *start_ptr = socket_mnt->recv_buf; //json起始地址
UINT8 *current_ptr = socket_mnt->recv_buf;
BOOL has_find_json_start = FALSE;
UINT32 count = 0;
osDelay(50); //等主线程完成操作。因为刚开始tcp线程还没建立,要先挂起接收线程,所以延时50ms等初始线程挂起本线程
while(1)
{
recved_len = recv(socket_mnt->socket_fd, socket_mnt->recv_buf + socket_mnt->recved_len, TCP_BIG_DATA_BUF_LEN, 0);
//recved_len = recv(socket_mnt->socket_fd, socket_mnt->recv_buf, TCP_RECV_BUF_LEN, 0);
//socket异常,可能是对端关闭。
if (recved_len <= 0)
{
//if (errno)
{
socket_mnt->tcp_status = TCP_DISCONNECTED; //重置socket状态
vTaskSuspend(NULL); //挂起任务自身
}
//恢复状态后,重置变量
socket_mnt->recved_len = 0;
has_find_json_start = FALSE;
start_ptr = socket_mnt->recv_buf;
current_ptr = socket_mnt->recv_buf;
count = 0;
continue;
}
socket_mnt->recved_len += recved_len;
//SCB_CleanInvalidateDCache_by_Addr((uint32_t *)socket_mnt->recv_buf, 1024 * 10);
write_tcp_msg(socket_mnt->recv_buf, socket_mnt->recved_len);
FIND_JSON_START:
if (!has_find_json_start)
{
//从接收缓冲区socket_mnt->recv_buf开始搜索左花括号,搜索长度是socket_mnt->recved_len
start_ptr = socket_mnt->recv_buf;
//找json数据的第一个左大括号
for (UINT32 i = 0; i < socket_mnt->recved_len; i++)
{
if ('{' == socket_mnt->recv_buf)
{
has_find_json_start = TRUE;
start_ptr = &socket_mnt->recv_buf;
break;
}
}
//没有找到json起点,抛弃这一次数据
if (!has_find_json_start)
{
socket_mnt->recved_len = 0;
continue;
}
else
{
count = 0;
}
}
//找到json起点
if (!count) //如果大括号计数为0,从第一个左大括号位置开始搜索。否则就是对端发送半包数据
{
current_ptr = start_ptr;
}
for (; current_ptr < socket_mnt->recv_buf + socket_mnt->recved_len; current_ptr++)
{
if ('{' == *current_ptr)
{
count++;
}
else if ('}' == *current_ptr)
{
count--;
}
if (0 == count) //找到一帧数据
{
//将这一帧数据添加到队列
if (!queue_is_full(&socket_mnt->json_msg_queue.queue))
{
INT32 tail = queue_get_tail(&socket_mnt->json_msg_queue.queue);
UINT32 data_len = (current_ptr - start_ptr) + 1 + 1; //最后+1,是为了拼凑成字符串
UINT8 *data = (UINT8 *)json_malloc(data_len);
if (data)
{
memset(data, 0, data_len);
memcpy(data, start_ptr, data_len - 1);
socket_mnt->json_msg_queue.fifo[tail] = data;
queue_push(&socket_mnt->json_msg_queue.queue);
}
}
//__packed UINT8* packd_ptr = socket_mnt->recv_buf;
socket_mnt->recved_len -= current_ptr - socket_mnt->recv_buf + 1; //计算剩余长度
if (socket_mnt->recved_len)
{
UINT8 *data = (UINT8 *)os_malloc(socket_mnt->recved_len);
memset(data, 0, socket_mnt->recved_len);
//UINT8 *tmp = (UINT8*)(current_ptr + 1);
memcpy(data, current_ptr + 1, socket_mnt->recved_len);
osDelay(200);
write_tcp_msg(socket_mnt->recv_buf, 0x65);
osDelay(200);
write_tcp_msg(current_ptr + 1, socket_mnt->recved_len);
osDelay(200);
//memcpy((void *)socket_mnt->recv_buf, (void *)data, socket_mnt->recved_len);
os_free(data);
//memcpy((void *)socket_mnt->recv_buf, (void *)(current_ptr + 1), socket_mnt->recved_len); //把剩余的数据挪到缓冲起始地址
write_tcp_msg(socket_mnt->recv_buf, 0x65);
}
has_find_json_start = FALSE;
goto FIND_JSON_START; //重新开始找json起始括号,可以处理粘包情况
}
}
}
}
socket_mnt->recv_buf是挂接的SDRAM前16M,__attribute__((at(SDRAM_BANK_ADDR))) UINT8 tcp_recv_buf[TCP_BIG_DATA_BUF_LEN] = { 0 };
MPU配置已经贴出来了,配置为normal存储类型
现在的测试结果是,程序不会异常。但是读取一段内存数据,如果不是4字节对齐的地址,读出数据不对,如果是4字节对其地址,读出的就对的。
标注红色的就是测试代码,打印出来。current_ptr是想要读取一段内存的数据,类型是UINT8*
这段代码是接收json消息的代码,处理消息粘包和半包,并且将消息放入消息队列。在处理粘包的时候,需要对数据切片,可能会遇到非4字节对齐的地址 |
|