当前位置: 首页 > news >正文

FreeModbus释放底层的 TCP 监听端口

背景

有Modbus和scpi两种协议,在使用过程中要切换,每次切换要给给对应协议绑定端口

问题

在每次切换协议之前都这样操作,把所有连接都关闭仔进行重新绑定

// 尝试禁用ModbuseMBDisable();// 尝试关闭SCPI服务器的监听和客户端连接if(server_state.listen_pcb!=NULL){tcp_close(server_state.listen_pcb);server_state.listen_pcb=NULL;}if(server_state.client_pcb!=NULL){tcp_close(server_state.client_pcb);server_state.client_pcb=NULL;server_state.connected=0;}

但是失败
结果:这样修改后,开机后protocol=1能直接连上设置的 192.168.1.111 port: 501 Modbus

面板改成选scpi后两种协议都不能使用,再改回Modbus后modbus可以使用,scpi不能用

开机后protocol=0能直接连上设置的 192.168.1.111 port: 501 scpi , 此时端口成功绑定

改成Modbus后modbus可以使用,scpi不能用

面板再改成选scpi后两种协议都不能使用,此时端口绑定失败

原因

这次失败的原因在于 FreeModbus 库的 eMBDisable() 函数默认只停止协议状态机,并不会释放底层的 TCP 监听端口(Listening Socket)。

  1. 资源未释放:在 Modbus TCP 模式下,eMBDisable()最终调用的是vMBTCPPortDisable(),而在porttcp.c中,这个函数仅尝试关闭已连接的客户端 PCB,完全没有处理正在监听的 PCB (pxPCBListen)
  2. 库配置限制:FreeModbus 默认将MB_PORT_HAS_CLOSE设置为0,这导致eMBClose()函数实际上是空的。
  3. 现象解释
    • 当从 Modbus 切换到 SCPI 时,Modbus 的监听端口依然在占用(因为它没被关闭)。
    • SCPI 尝试tcp_bind同一个端口,自然返回8(ERR_USE)。
    • 当切回 Modbus 时,Modbus 重新初始化并覆盖了之前的指针,但旧的监听 PCB 依然挂在协议栈里(资源泄露),虽然能连上,但此时协议栈状态已经非常混乱。

最终解决方法

我们需要强制开启 Modbus 库的资源释放功能,并在切换时显式调用它。

步骤 1:开启 Modbus 库的关闭功能

在 mbconfig.h中,将MB_PORT_HAS_CLOSE定义为1

添加了:

#defineMB_PORT_HAS_CLOSE(1)

步骤 2:在切换逻辑中添加彻底关闭调用

在 user_mb_app_m.c的cleanup_all_protocols函数中,添加对eMBClose()的调用。

核心修改如下:

staticvoidcleanup_all_protocols(void){// 1. 禁用 Modbus 状态机eMBDisable();// 2. 彻底关闭 Modbus 端口监听(关键:释放 pxPCBListen)eMBClose();// 3. 彻底清理 SCPI 资源if(server_state.client_pcb!=NULL){tcp_abort(server_state.client_pcb);server_state.client_pcb=NULL;server_state.connected=0;}if(server_state.listen_pcb!=NULL){tcp_close(server_state.listen_pcb);server_state.listen_pcb=NULL;}}

验证说明

  • 为什么这次会成功?
    • 因为eMBClose()会通过pvMBFrameCloseCur指针最终调用到porttcp.c中的vMBTCPPortClose()
    • vMBTCPPortClose()会显式调用prvvMBPortReleaseClient( pxPCBListen ),这才会真正向 LwIP 发出关闭监听端口的指令。
  • 后续测试
    再次切换。切换到 SCPI 后,观察到端口顺利绑定。
http://www.jsqmd.com/news/722348/

相关文章:

  • 上海物联网应用开发平台选型指南:架构机制与工程落地的核心考量
  • Ansys | 传统烤箱 vs 对流烤箱:饼干加热过程的热分析对比
  • 构建你的 AI 原生工业数据底座
  • IwrQk:免费开源的Iwara跨平台客户端完整使用指南
  • Kubernetes密钥管理实战:基于AWS Parameter Store的Secret自动同步方案
  • ARM PMU性能监控单元架构与RLU/RLH机制解析
  • 告别裸奔CAN!用STM32+CanFestival实现设备间基础通信(附对象字典配置心得)
  • 告别数据丢失焦虑:用DiskGenius给老硬盘MBR转GPT的保姆级图文教程
  • 3个关键步骤实现TigerVNC在国产ARM平台的高性能适配
  • Movelt2 规划场景 ROS API
  • 终极指南:如何快速重置Cursor AI编辑器试用限制,恢复完整功能
  • 【2026实测】论文AI率居高不下?3大高阶指令+4款工具快速降AI指南
  • SAP批次管理配置保姆级教程:从激活到查找策略,手把手带你走通全流程
  • 2026年黄金高价回收无套路:从检测到变现的全流程技术解析 - 优质品牌商家
  • 工业数据采集系统选型与误差控制实战指南
  • FPGA在高性能计算中的优势与应用实践
  • 告别C盘爆红!Windows Cleaner智能清理工具全攻略
  • ARM嵌入式认证考试全面指南
  • 湛江黑石材技术深度拆解:工艺、性能及靠谱选型推荐 - 优质品牌商家
  • 云原生技术体系解析
  • Windows Cleaner:3步解决C盘空间不足的智能清理神器
  • LLM 数据采集指南:提高AI数据采集成功率的4个技巧
  • 你的桌面需要一只会打鼓的猫咪吗?BongoCat让工作不再孤单
  • 【山海鲸实战案例】如何通过下拉菜单组件,控制图片内容的切换?
  • 2026深圳公司注册地址挂靠政策解读:2026年深圳注册公司全流程及费用,代理记账服务收费标准,优选指南! - 优质品牌商家
  • 企业微信 API 老是调不通?基本都是这几个问题
  • 2026 年4月首发:装修行业GEO优化服务商综合实力排行与选型参考
  • 《月球基底建造:以十六字混元道学为骨架,构建地月闭环生存与 AI 自主管控全系统》
  • 量子计算噪声挑战与零噪声外推技术解析
  • 深入UDS 0x23服务:从内存映射到安全访问,搞懂汽车ECU数据读取的那些‘坑’