FreeModbus释放底层的 TCP 监听端口
背景有Modbus和scpi两种协议在使用过程中要切换每次切换要给给对应协议绑定端口问题在每次切换协议之前都这样操作把所有连接都关闭仔进行重新绑定// 尝试禁用ModbuseMBDisable();// 尝试关闭SCPI服务器的监听和客户端连接if(server_state.listen_pcb!NULL){tcp_close(server_state.listen_pcb);server_state.listen_pcbNULL;}if(server_state.client_pcb!NULL){tcp_close(server_state.client_pcb);server_state.client_pcbNULL;server_state.connected0;}但是失败结果这样修改后开机后protocol1能直接连上设置的 192.168.1.111 port: 501 Modbus面板改成选scpi后两种协议都不能使用再改回Modbus后modbus可以使用scpi不能用开机后protocol0能直接连上设置的 192.168.1.111 port: 501 scpi , 此时端口成功绑定改成Modbus后modbus可以使用scpi不能用面板再改成选scpi后两种协议都不能使用此时端口绑定失败原因这次失败的原因在于 FreeModbus 库的 eMBDisable() 函数默认只停止协议状态机并不会释放底层的 TCP 监听端口Listening Socket。资源未释放在 Modbus TCP 模式下eMBDisable()最终调用的是vMBTCPPortDisable()而在porttcp.c中这个函数仅尝试关闭已连接的客户端 PCB完全没有处理正在监听的 PCB (pxPCBListen)。库配置限制FreeModbus 默认将MB_PORT_HAS_CLOSE设置为0这导致eMBClose()函数实际上是空的。现象解释当从 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 端口监听关键释放 pxPCBListeneMBClose();// 3. 彻底清理 SCPI 资源if(server_state.client_pcb!NULL){tcp_abort(server_state.client_pcb);server_state.client_pcbNULL;server_state.connected0;}if(server_state.listen_pcb!NULL){tcp_close(server_state.listen_pcb);server_state.listen_pcbNULL;}}验证说明为什么这次会成功因为eMBClose()会通过pvMBFrameCloseCur指针最终调用到porttcp.c中的vMBTCPPortClose()。vMBTCPPortClose()会显式调用prvvMBPortReleaseClient( pxPCBListen )这才会真正向 LwIP 发出关闭监听端口的指令。后续测试再次切换。切换到 SCPI 后观察到端口顺利绑定。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2567323.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!