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

异常断开模拟

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 */
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

友思特新闻 | 友思特荣获广州科技创新创业大赛智能装备行业赛初创组优胜企业!

2024年11月19日&#xff0c;第十三届中国创新创业大赛&#xff08;广东广州赛区&#xff09;暨2024年广州科技创新创业大赛智能装备行业赛颁奖典礼隆重举行。 赛事奖项介绍&#xff1a;广州科技创新创业大赛智能装备行业赛 第十三届“中国创新创业大赛&#xff08;广东广州赛区…

Docker3:docker基础1

欢迎来到“雪碧聊技术”CSDN博客&#xff01; 在这里&#xff0c;您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者&#xff0c;还是具有一定经验的开发者&#xff0c;相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导&#xff0c;我将…

MySQL - 数据库基础 | 数据库操作 | 表操作

文章目录 1、数据库基础1.1为什么要有数据库1.2主流的数据库1.3连接MySQL1.4服务器、数据库、表的关系1.5 MySQL框架1.6 SQL分类1.7储存引擎 2.数据库操作2.1创建数据库2.2字符集和校验规则2.3删除数据库2.4修改数据库2.5备份与恢复2.6查看连接情况 3.表的操作3.1创建表3.2查看…

通过vite+vue3+pinia从0到1搭建一个uniapp应用

最近项目上要做一个app&#xff0c;选择了用uniapp作为开发框架&#xff1b;我大概看了一下uniapp的文档&#xff0c;根据文档从0到1搭了一个uniapp应用供大家参考。 因为本人习惯使用了WebStorm编译器&#xff0c;但是uniapp官方推荐使用HBuilder搭建&#xff0c;如果和我一样…

学习路之phpstudy--安装mysql5.7后在my.ini文件中无法修改sql_mode

windows环境下使用phpstudy安装mysql5.7后需要修改mysql中的sql_mode配置&#xff0c;但是在phpstudy中打开mysql配置文件my.ini后&#xff0c; 通过查找找不到sql_mode或sql-mode&#xff0c; 此时无法在my.ini文件中直接进行修改&#xff0c;可以使用mysql命令进行修改&#…

IDEA:2023版远程服务器debug

很简单&#xff0c;但是很多文档没有写清楚&#xff0c;wocao 一、首先新建一个远程jvm 二、配置 三、把上面的参数复制出来 -agentlib:jdwptransportdt_socket,servery,suspendn,address5005 四、然后把这串代码放到服务器中&#xff08;这里的0.0.0.0意思是所有IP都能访问&a…

ts: 定义一个对象接收后端返回对象数据,但是报错了有红色的红线为什么

问&#xff1a; const backendProgressData ref<object>&#xff08;{}&#xff09; 这是我的代码&#xff0c;但是当我进行使用的时候&#xff1a; backendProgressData.value xxxx接口返回数据progressData:{percentage:123,text:"文字"} 在template中{{…

解决Docker环境变量的配置的通用方法

我们部署的很多服务都是以Docker容器的形式存在的。 在运行Docker容器前&#xff0c;除了设置网络、数据卷之外&#xff0c;还需要设置各种各样的环境变量。 有时候&#xff0c;由于容器版本的问题&#xff0c;一些文档没有及时更新&#xff0c;可能同时存在多个新旧版本的环…

【腾讯云产品最佳实践】腾讯云CVM入门技术与实践:通过腾讯云快速构建云上应用

目录 前言 什么是腾讯云CVM&#xff1f; 腾讯云CVM的技术优势 基于最佳技术实践&#xff0c;使用腾讯云CVM搭建应用 1. 开通CVM实例 2. 连接CVM实例 3. 配置Web环境 4. 部署PHP应用 腾讯云CVM行业应用案例&#xff1a;电商平台的双十一攻略 1. 弹性伸缩解决高并发问题…

51c嵌入式~IO合集2

我自己的原文哦~ https://blog.51cto.com/whaosoft/11697814 一、STM32串口通信基本原理 通信接口背景知识 设备之间通信的方式 一般情况下&#xff0c;设备之间的通信方式可以分成并行通信和串行通信两种。并行与串行通信的区别如下表所示。 串行通信的分类 1、按照数据传…

七、电机三环控制

电机三环控制指的是&#xff0c;直流有刷电机三环&#xff08;电流环速度环位置环&#xff09;PID 控制。 1、三环PID控制原理 三环 PID 控制就是将三个 PID 控制系统&#xff08;例如&#xff1a;电流环、速度环以及位置环&#xff09;串联起来&#xff0c;然后对前一个系统…

NLP论文速读(多伦多大学)|利用人类偏好校准来调整机器翻译的元指标

论文速读|MetaMetrics-MT: Tuning Meta-Metrics for Machine Translation via Human Preference Calibration 论文信息&#xff1a; 简介&#xff1a; 本文的背景是机器翻译&#xff08;MT&#xff09;任务的评估。在机器翻译领域&#xff0c;由于不同场景和语言对的需求差异&a…

【Vue】Vue指令

目录 概念 作用 分类 内容渲染指令 属性绑定指令 事件绑定指令 条件渲染指令 v-if/v-else-if/v-else多分支渲染 v-show和v-if的区别 列表渲染指令 v-for中的key属性 双向绑定指令 示例&#xff1a;图片切换 示例&#xff1a;可折叠面板 示例&#xff1a;书架…

C++:类和对象(三)

1.深入了解构造函数 1.1初始化列表 引入&#xff1a;我们首先要知道&#xff0c;在类中我们是声明变量&#xff0c;在实例化的时候才是开空间&#xff0c;在调用构造函数的时候又分两段&#xff0c;一段是定义&#xff08;所有的成员变量进行定义&#xff09;&#xff0c;一段…

北京申请中级职称流程(2024年)

想找个完整详细点的申请流程资料真不容易&#xff0c;做个分享送给需要的人吧。 不清楚为什么说文章过度宣传&#xff0c;把链接和页面去掉了&#xff0c;网上自己找一下。 最好用windows自带的EDGE浏览器打开申请网站&#xff0c;只有在开始申请的时间内才可以进行网上申报&…

好用的js组件库

lodash https://www.lodashjs.com/https://www.lodashjs.com/ uuid 用于生成随机数&#xff0c;常用于生成id标识 GitHub - uuidjs/uuid: Generate RFC-compliant UUIDs in JavaScripthttps://github.com/uuidjs/uuid dayjs 常用于时间的处理 安装 | Day.js中文网 (fenxi…

php:使用socket函数创建WebSocket服务

一、前言 闲来无事&#xff0c;最近捣鼓了下websocket&#xff0c;但是不希望安装第三方类库&#xff0c;所以打算用socket基础函数创建个服务。 二、构建websocket服务端 <?phpclass SocketService {// 默认的监听地址和端口private $address 0.0.0.0;private $port 8…

Tailscale 自建 Derp 中转服务器(全程无 Docker + 无域名纯 IP 版本)

文章目录 整体大纲目的&#xff1a;为什么要建立 Derp 中转服务器云服务器安装 DerpDerp 中转服务器介绍安装 Go 环境通过 Go 安装 Derp处理证书文件自签一个域名给 Derp验证 Derp 是否启动 云服务器安装并登录 Tailscale第一种组合&#xff1a; 官方 Tailscale 账号 自己的 D…

shell--第一次作业

1.接收用户部署的服务名称 # 脚本入口 read -p "请输入要部署的服务名称&#xff1a;" service_name 2.判断服务是否安装 # 判断服务是否安装 if rpm -q "$service_name" &>/dev/null; then echo "服务 $service_name 已安装。" 已…

项目部署问题bug记录(长期更新)

一、编译相关 1.submodules/simple-knn/simple_knn.cu(90): error: identifier "FLT_MAX" is undefined me.minn { FLT_MAX, FLT_MAX, FLT_MAX }; 部署photoreg工程&#xff0c;在编译simple_knn的时候&#xff0c;报错&#xff1a; (photoreg) leelee…