tcp/ip异常断开调试笔记——lwip

news/2024/11/27 1:33:26/

问题一:异常掉线

异常断开模拟

1、单片机端做服务端(只监听一个客户端),电脑做客户端连接

2、尝试连接确定通信正常,断开网线。电脑客户端点击断开

3、经过一段时间(超过tcp/ip 3次握手时间)

4、接回网线后发现可以连接上但通信异常

原因分析

void StartDefaultTask(void *argument)
{/* init code for LWIP */MX_LWIP_Init();/* USER CODE BEGIN StartDefaultTask */struct sockaddr_in server_addr,client_addr;socklen_t sin_size;int recv_data_len;static uint8_t recv_data[RECV_DATA];again:sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd < 0){LWIP_TCP_DEBUG("Socket error\n");close(sockfd);vTaskDelay(100);goto again;}//server_addr.sin_family = AF_INET;server_addr.sin_addr.s_addr = htonl(INADDR_ANY);server_addr.sin_port = htons(LOCAL_PORT);memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1){LWIP_TCP_DEBUG("Unable to bind\n");close(sockfd);vTaskDelay(100);goto again;}if (listen(sockfd, BACKLOG) == -1){LWIP_TCP_DEBUG("Listen error\n");close(sockfd);vTaskDelay(100);goto again;}/* Infinite loop */for(;;){sin_size = sizeof(struct sockaddr_in);connected = accept(sockfd, (struct sockaddr *)&client_addr, &sin_size);LWIP_TCP_DEBUG("new client connected from (%s, %d)\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));int tcp_nodelay = 1;//don't delay send to coalesce packetssetsockopt(connected,IPPROTO_TCP,TCP_NODELAY,(void *) &tcp_nodelay,sizeof(int));while(1){recv_data_len = recv(connected, recv_data, RECV_DATA, 0);if (recv_data_len <= 0){break;}//			write(connected,recv_data,recv_data_len);writeToRxBuf(recv_data, recv_data_len);}if (connected >= 0){close(connected);}connected = -1;//osDelay(1);}/* USER CODE END StartDefaultTask */
}

服务端未收到正常断开消息导致一直阻塞recv_data_len = recv(connected, recv_data, RECV_DATA, 0);

解决方案

TCP的keepalive机制

STM32 LWIP Server、Client如何判断网络异常_lwip检测网络状态-CSDN博客

void StartDefaultTask(void *argument)
{/* init code for LWIP */MX_LWIP_Init();/* USER CODE BEGIN StartDefaultTask */struct sockaddr_in server_addr,client_addr;socklen_t sin_size;int recv_data_len;static uint8_t recv_data[RECV_DATA];int so_keepalive_val = 1;    //使能心跳机制int tcp_keepalive_idle = 3;  //发�?�心跳空闲周�? 单位:秒int tcp_keepalive_intvl = 3; //发�?�心跳间�? 单位:秒int tcp_keepalive_cnt = 3;   //重发次数
//	int tcp_nodelay = 1;         //不延时发送到合并�?int err = 0;again:sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd < 0){LWIP_TCP_DEBUG("Socket error\n");close(sockfd);vTaskDelay(100);goto again;}//使能心跳机制,默认没有使�?err = setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &so_keepalive_val, sizeof(int));if(err){}//server_addr.sin_family = AF_INET;server_addr.sin_addr.s_addr = htonl(INADDR_ANY);server_addr.sin_port = htons(LOCAL_PORT);memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1){LWIP_TCP_DEBUG("Unable to bind\n");close(sockfd);vTaskDelay(100);goto again;}if (listen(sockfd, BACKLOG) == -1){LWIP_TCP_DEBUG("Listen error\n");close(sockfd);vTaskDelay(100);goto again;}/* Infinite loop */for(;;){sin_size = sizeof(struct sockaddr_in);connected = accept(sockfd, (struct sockaddr *)&client_addr, &sin_size);//配置心跳�?测参数,默认参数时间很长。必须在accept之后,因为不是同�?个socket�?err = setsockopt(connected, IPPROTO_TCP, TCP_KEEPIDLE, &tcp_keepalive_idle, sizeof(int));err = setsockopt(connected, IPPROTO_TCP, TCP_KEEPINTVL, &tcp_keepalive_intvl, sizeof(int));err = setsockopt(connected, IPPROTO_TCP, TCP_KEEPCNT, &tcp_keepalive_cnt, sizeof(int));LWIP_TCP_DEBUG("new client connected from (%s, %d)\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));int tcp_nodelay = 1;//don't delay send to coalesce packetssetsockopt(connected,IPPROTO_TCP,TCP_NODELAY,(void *) &tcp_nodelay,sizeof(int));while(1){recv_data_len = recv(connected, recv_data, RECV_DATA, 0);//			recv_data_len = recv(connected, recv_data, RECV_DATA, MSG_DONTWAIT);//	        if (recv_data_len == -1)//	        {//	            if (errno == EAGAIN || errno == EWOULDBLOCK)//	            {//	            	osDelay(1);//	                continue;//	            }perror("read");exit(-1);//	            break;//	        }else if(recv_data_len > 0){//	        	writeToRxBuf(recv_data, recv_data_len);printf("recv client data : %s\n", recv_buf);//	        }else if(recv_data_len == 0){printf("client closed\n");//	            break;//	        }if (recv_data_len <= 0){break;}//						write(connected,recv_data,recv_data_len);writeToRxBuf(recv_data, recv_data_len);}if (connected >= 0){close(connected);}connected = -1;//osDelay(1);}/* USER CODE END StartDefaultTask */
}

问题二:卡死configASSERT( pxQueue->uxItemSize == 0 );

现象:客户端(电脑)显示还连着,可以发送数据,但是收不到数据。原因是已经先输入断言的死循环了。

如何调试以解决 configASSERT( pxQueue->uxItemSize == 0 );循环错误?- 合作伙伴和赞助商 / 恩智浦 - FreeRTOS 社区论坛

屏蔽了其他代码就留了个循环发送的还是会。最后换了个ide(keil)才解决


http://www.ppmy.cn/news/1550202.html

相关文章

【C++篇】深度解析 C++ List 容器:底层设计与实现揭秘

文章目录 须知 &#x1f4ac; 欢迎讨论&#xff1a;如果你在学习过程中有任何问题或想法&#xff0c;欢迎在评论区留言&#xff0c;我们一起交流学习。你的支持是我继续创作的动力&#xff01; &#x1f44d; 点赞、收藏与分享&#xff1a;觉得这篇文章对你有帮助吗&#xff1…

嵌入式Linux移植cJSON库

嵌入式Linux移植cJSON库 一、前言二、移植三、常用函数四、代码案例五、注意事项一、前言 在使用嵌入式系统做项目时,碰见了使用JSON格式数据的需求,所以需要移植cJSON库进行组织和解析数据。 二、移植 cJSON的github地址:https://github.com/DaveGamble/cJSON,可以在git仓…

僵尸毁灭工程 服务搭建 联机教程 无需公网IP、服务器

主要内容 什么是僵尸毁灭工程 搭建该服务&#xff0c;需要准备什么 详细步骤 1.下载并运行 SteamCMD 2.下载僵尸毁灭服务端 3.运行 MoleSDN 进行异地联机 4.小伙伴皮蛋加入鼠鼠服务器 完成联机 什么是僵尸毁灭工程 一款由The Indie Stone开发的开放世界生存模拟游戏。游…

WebRTC音视频同步原理与实现详解(上)

第一章、RTP时间戳与NTP时间戳 1.1 RTP时间戳 时间戳&#xff0c;用来定义媒体负载数据的采样时刻&#xff0c;从单调线性递增的时钟中获取&#xff0c;时钟的精度由 RTP 负载数据的采样频率决定。 音频和视频的采样频率是不一样的&#xff0c;一般音频的采样频率有 8KHz、…

【linux】插入新硬盘如何配置:格式化、分区、自动挂载(Ubuntu)

文章目录 具体方法GPT分区表&#xff08;GUID Partition Table&#xff09;&#xff08;建议都用这种分区方法&#xff09;MBR分区表方法&#xff08;最大支持2TB分区&#xff09;&#xff08;Master Boot Record&#xff09; 附加&#xff1a;如何查看硬盘的型号另外&#xff…

如何使用 Python 开发一个简单的文本数据转换为 Excel 工具

目录 一、准备工作 二、理解文本数据格式 三、开发文本数据转换为Excel工具 读取CSV文件 将DataFrame写入Excel文件 处理其他格式的文本数据 读取纯文本文件: 读取TSV文件: 四、完整代码与工具封装 五、使用工具 六、总结 在数据分析和处理的日常工作中,我们经常…

spark 3.4.4 利用Spark ML中的交叉验证、管道流实现鸢尾花分类预测案例选取最优模型

前情回顾 前面的案例中&#xff0c;介绍了怎么基于管道流实现啊鸢尾花案例&#xff0c;利用逻辑斯蒂回归模型预测。详细内容步骤可以参照相应的博客内容 本案例内容 在 Spark 中使用交叉验证结合逻辑回归&#xff08;Logistic Regression&#xff09;以及管道流&#xff08;P…

Sickos1.1 详细靶机思路 实操笔记

Sickos1.1 详细靶机思路 实操笔记 免责声明 本博客提供的所有信息仅供学习和研究目的&#xff0c;旨在提高读者的网络安全意识和技术能力。请在合法合规的前提下使用本文中提供的任何技术、方法或工具。如果您选择使用本博客中的任何信息进行非法活动&#xff0c;您将独自承担…