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

news2024/11/23 15:20:07

问题一:异常掉线

异常断开模拟

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 packets
		setsockopt(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 packets
		setsockopt(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 );

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2246088.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JavaScript获取URL参数常见的4种方法

&#x1f680; 个人简介&#xff1a;某大型国企资深软件开发工程师&#xff0c;信息系统项目管理师、CSDN优质创作者、阿里云专家博主&#xff0c;华为云云享专家&#xff0c;分享前端后端相关技术与工作常见问题~ &#x1f49f; 作 者&#xff1a;码喽的自我修养&#x1f9…

40分钟学 Go 语言高并发:并发下载器开发实战教程

并发下载器开发实战教程 一、系统设计概述 1.1 功能需求表 功能模块描述技术要点分片下载将大文件分成多个小块并发下载goroutine池、分片算法断点续传支持下载中断后继续下载文件指针定位、临时文件管理进度显示实时显示下载进度和速度进度计算、速度统计错误处理处理下载过…

《Object类》

目录 一、Object类 1.1 定义与地位 1.2 toString()方法 1.3 equals()方法 1.4 hashcode()方法 一、Object类 1.1 定义与地位 Object类是Java语言中的根类&#xff0c;所有的类&#xff08;除了Object类&#xff09;都直接或间接继承自Object。这就意味着在Java中&#xf…

Vercel 设置自动部署 GitHub 项目

Vercel 设置自动部署 GitHub 项目 问题背景 最近 Vercel 调整了其部署政策&#xff0c;免费版用户无法继续使用自动部署功能&#xff0c;除非升级到 Pro 计划。但是&#xff0c;我们可以通过配置 Deploy Hooks 来实现同样的自动部署效果。 解决方案 通过设置 Vercel 的 Dep…

2023年9月GESPC++一级真题解析

一、单选题&#xff08;每题2分&#xff0c;共30分&#xff09; 题号 123456789101112131415 答案 CDBCDBACACBBDDA 1. 我们通常说的 “ 内存 ” 属于计算机中的&#xff08;&#xff09;。 A. 输出设备 B. 输 ⼊ 设备 C. 存储设备 D. 打印设备 【答案】 C 【考纲知识点】…

Laravel对接SLS日志服务

Laravel对接SLS日志服务&#xff08;写入和读取&#xff09; 1、下载阿里云的sdk #通过composer下载 composer require alibabacloud/aliyun-log-php-sdk#对应的git仓库 https://github.com/aliyun/aliyun-log-php-sdk2、创建sdk请求的service <?phpnamespace App\Ser…

SQL注入--报错注入--理论

什么是报错注入&#xff1f; 正常用户向数据库查询数据&#xff0c;查询语句出现错误时会返回报错信息。 如果数据库对查询语句的输入和数据的输出没有进行合理检测&#xff0c;攻击者就可以通过构造语句让报错信息中包含数据库的内容。 基本利用形式 updatexml注入 函数形…

ECharts柱状图-带圆角的堆积柱状图,附视频讲解与代码下载

引言&#xff1a; 在数据可视化的世界里&#xff0c;ECharts凭借其丰富的图表类型和强大的配置能力&#xff0c;成为了众多开发者的首选。今天&#xff0c;我将带大家一起实现一个柱状图图表&#xff0c;通过该图表我们可以直观地展示和分析数据。此外&#xff0c;我还将提供…

002 MATLAB语言基础

01 变量命名规则 变量名只能由字母、数字和下划线组成&#xff0c;且必须以字母开头&#xff1b; 变量名区分字母的大小写&#xff1b; 变量名不能超过最大长度限制&#xff1b; 关键字不能作为变量名&#xff0c;如for、end和if等&#xff1b; 注意&#xff1a;存变量命名时…

Java 对象头、Mark Word、monitor与synchronized关联关系以及synchronized锁优化

1. 对象在内存中的布局分为三块区域&#xff1a; &#xff08;1&#xff09;对象头&#xff08;Mark Word、元数据指针和数组长度&#xff09; 对象头&#xff1a;在32位虚拟机中&#xff0c;1个机器码等于4字节&#xff0c;也就是32bit&#xff0c;在64位虚拟机中&#xff0…

RTL8211F 1000M以太网PHY指示灯

在RK3562 Linux5.10 SDK里面已支持该芯片kernel-5.10/drivers/net/phy/realtek.c&#xff0c;而默认是没有去修改到LED配置的&#xff0c;我们根据硬件设计修改相应的寄存器配置&#xff0c;该PHY有3个LED引脚&#xff0c;我们LED0不使用&#xff0c;LED1接绿灯&#xff08;数据…

通过IIC访问模块寄存器[ESP--1]

上一节中&#xff0c;我们简单使用ESP函数来从主机视角扫描所有的IIC设备|上一篇文章的链接|&#xff0c;但是并不存在主从机之间的交流。这显然是不合理的&#xff0c;这个小节我们来学习如何实现主从机之间的通信 模块的寄存器 不说最简单的电阻电容电感&#xff0c;稍微复…

Spring Cloud Netflix 系列:Eureka 经典实战案例和底层原理解析

文章目录 前言Eureka 简介架构设计工作流程 项目 demo 构建Eureka Server 的搭建Eureka Client 的配置补充说明 运行效果 深入使用Eureka 注册中心添加认证搭建 Eureka 集群实现高可用双节点集群搭建 运行效果补充说明为什么要配置 不同host 原理解析服务注册、心跳续期详细流程…

数字赋能,气象引领 | 气象景观数字化服务平台重塑京城旅游生态

在数字化转型的浪潮中&#xff0c;旅游行业正以前所未有的速度重塑自身&#xff0c;人民群众对于高品质、个性化旅游服务需求的日益增长&#xff0c;迎着新时代的挑战与机遇&#xff0c;为开展北京地区特色气象景观预报&#xff0c;打造“生态气象旅游”新业态&#xff0c;助推…

(python)unittest框架

unittest unnitest介绍 TestCase测试用例 书写真正的用例脚本

Hadoop 系列 MapReduce:Map、Shuffle、Reduce

文章目录 前言MapReduce 基本流程概述MapReduce 三个核心阶段详解Map 阶段工作原理 Shuffle 阶段具体步骤分区&#xff08;Partition&#xff09;排序&#xff08;Sort&#xff09;分组&#xff08;Combine 和 Grouping&#xff09; Reduce 阶段工作原理 MapReduce 应用场景Map…

微服务即时通讯系统的实现(服务端)----(1)

目录 1. 项目介绍和服务器功能设计2. 基础工具安装3. gflags的安装与使用3.1 gflags的介绍3.2 gflags的安装3.3 gflags的认识3.4 gflags的使用 4. gtest的安装与使用4.1 gtest的介绍4.2 gtest的安装4.3 gtest的使用 5 Spdlog日志组件的安装与使用5.1 Spdlog的介绍5.2 Spdlog的安…

uniapp发布android上架应用商店权限

先看效果&#xff1a; 实现原理&#xff1a; 一、利用uni.addInterceptor的拦截器&#xff0c;在一些调用系统权限前拦截&#xff0c;进行弹窗展示&#xff0c;监听确定取消实现业务逻辑。 二、弹窗是原生nativeObj进行drawRect绘制的 三、权限申请调用使用的 plus.android.…

AmazonS3集成minio实现https访问

最近系统全面升级到https&#xff0c;之前AmazonS3大文件分片上传直接使用http://ip:9000访问minio的方式已然行不通&#xff0c;https服务器访问http资源会报Mixed Content混合内容错误。 一般有两种解决方案&#xff0c;一是升级minio服务&#xff0c;配置ssl证书&#xff0c…

【代码pycharm】动手学深度学习v2-08 线性回归 + 基础优化算法

课程链接 线性回归的从零开始实现 import random import torch from d2l import torch as d2l# 人造数据集 def synthetic_data(w,b,num_examples):Xtorch.normal(0,1,(num_examples,len(w)))ytorch.matmul(X,w)bytorch.normal(0,0.01,y.shape) # 加入噪声return X,y.reshape…