ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

104协议滑动窗口参数k/w与超时配置实战指南

104协议滑动窗口参数k/w与超时配置实战指南 1. 为什么一定要搞懂104协议滑动窗口参数变电站远动调试现场主站和厂站之间104链路频繁断开重连后过一会儿又断站端报文显示“接收序号溢出”主站侧显示“t1超时”两边都在骂对方规约没写好。这种场景在电力自动化工程里太常见了十次里有八次问题根源都出在滑动窗口参数k、w没配对或者跟实际的通道质量、报文长度、间隔时间根本不匹配。IEC 60870-5-104协议在国内电力调度自动化系统里几乎是唯一的主流通信规约它把IEC 60870-5-101的串口报文完整映射到TCP/IP网络上靠TCP提供可靠传输但又在应用层自己搞了一套确认机制——这就是104协议最核心、也最容易出问题的地方滑动窗口参数k和w还有一组超时参数t0、t1、t2、t3。搞不懂这几个参数你连报文都看不懂更别说定位链路抖动、主备切换异常、全站数据中断这些疑难杂症。这篇文章我按实际工程视角把这几个参数从原理到配置再到排障一层层拆开讲清楚。适合三类人看刚入门的电力自动化调试人员被104链路问题折磨过的运维工程师以及写远动通信程序需要做协议栈调优的研发同学。看完你至少能做到三件事配参数不再靠猜、看报文能定位滑动窗口相关问题、遇到主站和厂站参数不一致能拿出依据说服对方。2. 104协议和101协议的关系先说透2.1 从101到104串口到网络的一次关键跃迁IEC 60870-5-101是远动设备串口通信的标准早期变电站、调度端的自动化系统绝大部分都是通过RS-232、RS-485串口用101协议传遥测、遥信、遥控、遥调数据。101协议用FT1.2帧格式一帧最长的固定帧也就255个字节链路层靠“发送-停止-等待应答”的方式保证可靠一发一收效率低但简单可靠特别适合串口这种低带宽、低并发、信道易受干扰的场景。后来网络技术普及调度数据网把变电站和主站连起来了再拿101跑TCP就非常不合适一方面是101的链路层轮询机制在TCP上没有任何必要TCP本身就能保证字节流不重不漏另一方面是101一帧数据量太小遥测全数据动不动几百上千个点一发一停等确认网络延迟稍微高一点全数据刷新就慢得离谱。所以IEC TC57工作组在1997年前后搞出了IEC 60870-5-104本质就是“101的应用层数据结构叠加TCP/IP传输再引入一套面向流的传输控制机制”。104协议只定义APCI应用协议控制信息这部分ASDU应用服务数据单元全部沿用101的。也就是说你懂101的ASDU类型、信息体结构学104只需要搞清楚APCI里的控制域和参数机制即可。2.2 滑动窗口到底是哪两个参数104协议里滑动窗口实际包含两个方向的控制参数k发送方在未收到接收方确认的情况下最多可以连续发送的APDU数量协议默认值是12。w接收方在发出确认之前最多允许接收的APDU数量协议默认值是8。这两个参数都在RFC的IEC 60870-5-104协议文档里给出建议值但并没有严格要求必须用默认值关键是主站和厂站两侧的k/w必须按照“对端能力”协商好实际工程中绝大多数情况下直接采用默认值k12、w8就够了。你可能会觉得TCP里已经有了滑动窗口104为什么还要自己来一套这恰恰是104设计的精髓TCP的滑动窗口是内核协议栈在传输层控制的104所在的应用进程如果接收区处理不过来比如CPU繁忙、数据库写库慢、多路接入复用同一线程池TCP层不一定能及时感知。104在应用层做k/w控制相当于是把“流控”从内核态提升到了业务态确保应用处理的背压能反馈到对端。进一步说104的k/w参数是报文级别的确认机制而TCP是字节流级别的确认机制。两者叠加既保证网络层的可靠又兼顾应用层的处理能力。很多初学者容易把两者混为一谈理解成“TCP都已经可靠了104的k/w是不是多余的”——实际调试中你会看到即便TCP连接正常如果主站应用处理不过来不回复S帧或I帧确认发送方依然会因为k参数耗尽而触发t1超时最终断开整个TCP连接。3. k和w参数深度拆解编号机制、计算方式和阈值推导3.1 发送序号N(S)、接收序号N(R)与I帧/S帧/U帧要理解k和w绕不开104帧格式里控制域的那三个类型。104的APCI控制域第一个字节定义帧类型I帧信息传输帧控制域第一位是0用于承载ASDU数据携带发送序号N(S)和接收序号N(R)。I帧是唯一能携带数据的帧。S帧监视帧控制域第一位是1、第二位是0只有接收序号N(R)用于纯确认不能带数据。U帧非平衡帧控制域第一位是1、第二位是1用于链路控制包括STARTDT、STOPDT、TESTFR三类。U帧没有序号。I帧的N(S)、N(R)各自占用6位也就是说序号的取值范围是0到63协议规定采用模64的计数方式意思是序号到达63后下一帧从0重新开始。实际解析时你需要把序号看作环形的判定新旧帧要用“模64差”来做不能简单地拿数值大小比较。3.2 k值耗尽意味着什么k参数这样定义发送方发送了某个I帧其N(S)值记为s那么发送方可以继续发送的条件是s - N(S)_last_acked k其中N(S)_last_acked是对端最后确认的发送序号即对端返回的N(R)减去1。通俗地说如果发送方已经连续发了k个I帧都没收到任何确认那就必须停下来等待对端回S帧或I帧来确认。k12时发送方最多能“在途”——已经在网络上但尚未被确认的I帧数量为12个。有人会问既然TCP已经有拥塞窗口和接收窗口104的k12是不是太小了这里要注意104的k是报文数量而一个报文一个APDU可以承载多个信息体地址的数据。比如遥测全数据帧一个APDU塞满了可能包含上百个遥测点12个APDU足以覆盖几千个数据点在调度自动化场景里是完全够用的。但如果你在配置里把k改得很小比如k2那么只要对端稍微处理慢一点发送方很快就会被卡住表现就是“链路正常但数据不刷新”你必须通过抓包才能看出来是不是发送窗口堵了。3.3 w值决定确认频率w参数定义在接收侧接收方每收到w个I帧必须发出一个确认帧S帧或携带N(R)的I帧来向发送方报告“我已经收到你了”。协议允许接收方每收一帧就确认一次w1也允许攒到w个才确认但不得超过w。w默认值8就意味着接收方最多允许8个I帧“悬而未确认”。配合k12在最极端情况下发送方发了12帧接收方可能只确认了4帧每8帧确认一次剩下的8帧还在途中或尚未确认发送方的在途帧数正好小于12能继续发。这两者是有配合关系的。w大于k是协议明确禁止的因为这会导致接收方最多允许w个未确认帧而发送方最多只能发k个且kw时接收方可能永远凑不够w帧去确认链路就会死锁。这是配置参数时最容易踩的坑。3.4 为什么k和w是12和8而不是其他值从工程实践来看k12、w8这个组合经过大量现场验证是兼顾链路效率、误码恢复速度和实现复杂度的经验值。有兴趣的工程师可以做一下简单测算假设每个I帧发送周期为100ms这是典型的全数据召唤轮询节奏k12意味着发送方在完全不收到确认的情况下可以持续发送1.2秒的数据而不被打断。这给接收方留出了充足的应用处理时间。如果k1发送方发一帧就要等确认往返时延RTT是100ms的话链路吞吐直接腰斩数据刷新速度无法接受。再考虑误码场景TCP重传由内核处理104应用层不使用TCP_NODELAY禁用Nagle算法时可能出现小报文延迟但这些都不会导致104报文的序号错乱。k12给了接收方足够的时间去缓冲乱序TCP保证有序、处理写库、拼接全数据同时又不会让故障恢复时间过长——因为一旦丢链t1超时后重连k再大也不会让缓冲数据“后补”反而导致大量数据堆积在应用缓冲区一旦链路恢复新老数据混合上送容易造成主站数据库写入错乱。4. 和滑动窗口强绑定的三个超时参数t0、t1、t2、t34.1 t1发送确认超时t1是发送方等待接收方确认的最长时间默认15秒。只要你发了一个I帧/U帧但对方一直没回任何确认帧超过t1就判定链路异常主动关闭TCP连接。t1和k参数是联动的k控制“最多可以发多少个不确认帧”t1控制“我方在发出某个需要确认的帧后最多等多久”。如果你把k调大但t1没跟着调那么可能出现这种情况——发送方在t1时间内发了12帧可能100ms一帧12帧才1.2秒本来没到t1但由于接收方处理太慢没能及时确认发送方在1.2秒后就无帧可发干等到15秒超时断开。此时你会观察到链路断开的触发点不是窗口溢出而是t1超时。4.2 t2接收方确认触发时间t2是接收方在收到数据后如果没有立即发送确认需要启动一个定时器在t2超时后必须发一个S帧确认。默认值是10秒。这里有个硬性约束t2必须小于t1。原因很明显——发送方在t1时间内没等到确认就会断链如果接收方的确认定时器t2比t1还长那确认永远不可能及时到达链路必断。协议文档还特别标注了一个测试要求t1的取值应该大于t2通常工程上t1取15秒、t2取10秒留出5秒的余量。4.3 t3链路空闲测试帧周期t3是双方在没有数据帧交互时的链路保活周期默认20秒。如果发送方在t3时间内既没有发送过I帧也没有收到过对端的任何帧就需要主动发送TESTFR_ACTU帧测试激活来探测链路。对端收到后必须回TESTFR_CON。t3和t2的关系也需要注意t3大于t2这是为了防止链路空闲期间出现假死——如果有数据在传t2会触发S帧确认如果完全空闲t3触发U帧测试。两者形成了链路健康的完整探活机制。4.4 一组完整的链路时序把参数串起来实际链路中这组参数是这样配合的TCP连接建立后主站发送STARTDT_ACT启动数据传输收到厂站回STARTDT_CON后方可传输I帧。主站开始周期发送总召唤或突发遥信变位报文。每发一个I帧N(S)递增每收一个I帧N(R)递增。厂站收到I帧后可能立即回S帧确认如果它想尽快释放窗口也可能攒到w8帧才确认。关键条件是t210秒内必须确认。若网络抖动或厂站应用阻塞主站发了12帧k12后未收到任何确认主站停止发送启动t115秒的定时器。若15秒内仍无确认主站主动断开TCP连接等待重新建立。理解了这条链路你就知道为什么两个方向的超时参数必须严格满足t2 t1且t3一般大于t2。任何一家的参数表如果违反了这个约束链路一定不稳定。5. 滑动窗口参数相关的帧格式与序号机序细节5.1 控制域的位级解读只看参数不理解帧格式排障时还是抓瞎。104协议控制域共4个字节值得逐位看一下I帧控制域第一字节: 0 | 0 | 0 | 0 | 0 | N(S)高两位 第二字节: N(S)低6位 第三字节: 0 | 0 | 0 | 0 | 0 | N(R)高两位 第四字节: N(R)低6位S帧控制域第一字节: 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0U帧控制域: 1 | 1 | 0 | 0 | 1/0 | 1/0 | 0 | 0后四位定义STARTDT/STOPDT/TESTFR类别注意TCP是流式传输一个TCP包可能包含多个104 APDU也可能一个APDU被拆成两个TCP段。在程序实现或抓包分析时必须按照APDU的起始字符0x68和长度字段来切分包不能简单地认为“一个TCP包就是一个104帧”。5.2 序号回绕模64与比较陷阱序号到达63后回0这是最容易写错bug的地方。假设当前N(S)60连续发5帧序号依次是60、61、62、63、0。如果接收方处理完61后CPU卡顿接着收到0不能认为“0 61所以是旧帧”而丢弃——必须用模64差值判断。判断新旧的正确逻辑是若 (new_seq - last_seq) mod 64 的取值在0到31之间则认为new_seq更新如果差值在32到63之间则认为new_seq更旧可能发生了回绕或乱序。这其实就是计算机网络里常见的“滑动窗口序号空间减半”原则因为N(S)只有6位有效差值超过31就不可信了。踩过的坑有些开发用有符号int8直接比较大小序号从63回绕到0时必然出错表现为链路偶尔丢弃合法帧、接收序号溢出、主站频繁重启总召唤等严重故障。5.3 接收序号溢出与不确认帧累计104协议规定接收方如果发现收到的N(S)不等于自己期望的值期望值最后一次确认的N(R) mod 64就认为发送序号“溢出”或乱序必须丢弃该帧但不断开链路。这个“溢出”在很多厂家的报文解析软件里直接用英文显示为“sequence error”或者“unexpected sequence number”。最经典的误报场景发送方在断链前发了一堆I帧这些帧堆积在TCP缓冲区。断链后TCP连接销毁这些数据没了但发送方的应用层没有重置N(S)——重连后发送方从N(S)12开始发接收方在新建连接里期望N(S)0全部丢弃链路一直处于“收帧丢弃”状态直到发送方重启应用或者重发总召唤强制对端重置序列号。解决方法是104协议要求每次STARTDT_ACT/STARTDT_CON之后双方的发送序号和接收序号都必须从0开始。所以每次重连后务必检查两端是否在STARTDT_CON后重置了序号计数器。有些老设备固件没做这个重置就会出现“连上就断开断开再连仍然异常”的问题。6. 参数配置实操与场景化调优建议6.1 标准参数配置表下面的表格是工程上最常用的一组配置适用于电力调度主站、变电站远动装置和规约转换器参数名推荐值作用配置位置k12最大未确认I帧数厂站、主站两侧w8接收方确认前最大可收帧数厂站、主站两侧t010秒建立连接后等待STARTDT_CON超时主站侧发起方t115秒发送后等待确认超时两侧t210秒接收方确认触发定时器两侧t320秒链路空闲测试周期两侧最大APDU长度253字节常用240或250单个应用报文最大长度两侧提示k值建议不超过15w不超过k-2。某些厂家型号的装置自带参数范围限制配置时需查阅具体设备的规约参数手册。如果你的系统里有两个主站同时接入各主站连接是独立TCP链路滑动窗口参数可以按各主站的实际处理能力分开设置互不影响。6.2 低带宽窄带场景怎么调调度数据网一般带宽够用但遇到光纤专线质量差、时延长的情况参数需要针对性调整。比如卫星链路或4G无线公网RTT达到300ms甚至更高默认的k12可以发的报文量很大但因为确认回来慢链路吞吐被RTT卡住。此时可以考虑适当增大t1到20秒甚至30秒t2相应调整到15秒同时保持k不变或减小到8。原因是无线公网环境下TCP重传本身就频繁如果t1还是15秒偶尔一次网络拥塞导致多个TCP段重传应用层很快就触发t1断链。把t1调大后TCP自身恢复能力先起作用104应用层就不会那么敏感。注意t1并不是越大越好——t1太大会导致故障发现延迟整个调度系统对通道中断的感知变慢这在电力调度场景里是不可接受的。通常t1上限不建议超过30秒。6.3 高并发主站接入怎么调如果主站同时接入几十上百个厂站每个厂站一条TCP连接主站侧的应用处理能力就是瓶颈。此时w不宜设得太小比如w1因为每个连接频繁回S帧会给主站CPU和网络栈带来很大压力。建议保持w8或适当增大到12、16让接收方批量确认同时增大k可以让发送方更激进地发包但前提是主站侧的TCP接收缓冲区和应用缓冲区足够大。6.4 参数修改后的验证步骤修改k/w/t1/t2/t3不是改完就完事必须做一轮完整验证检查两端参数是否一致直接在报文里看S帧的N(R)和发送方的N(S)变化节奏是否符合预期。做一次全数据总召唤确认遥测、遥信全数据能完整上送观察是否有“卡死”“序号异常”现象。拔掉网线或关闭对端端口模拟通道中断确认t1超时断链时间是否符合配置值。恢复通道确认重连后序号回0、数据恢复周期是否符合预期。连续运行24小时观察主站侧是否有频繁重连记录、厂站侧是否有通信告警。7. 常见故障排查与典型报文分析7.1 故障一链路反复断开重连现象主站日志里每十几秒出现一次“TCP连接建立-断开-重建”厂站指示灯闪烁。排查流程抓包确认断开方向如果是主站主动断开查看主站发给厂站的最后几个报文是否是因为t1超时主站发了I帧后15秒无确认。如果是厂站主动断开大概率厂站t1超时或TCP保活探测失败。查看断开前是否有大量无确认I帧堆积如果厂站收到I帧后不回复S帧也不回复I帧说明厂站应用层卡死或缓冲区溢出。用wireshark的104协议解析插件wireshark内置了IEC 60870-5-104解析器查看双方的N(S)/N(R)变化判断哪一侧的确认逻辑没生效。常见原因厂站装置的程序里没实现t2定时器只有收到下一帧才顺手回确认一旦数据流停下来确认永远不会发主站必然t1超时。7.2 故障二序号溢出反复出现数据却不刷新现象厂站和主站TCP连接正常但主站收到的遥测数据永远是旧值抓包看到大量“sequence number error”。原因重连后序号未重置。发送方还在用断链前的N(S)继续发接收方期望的是0顺着这个思路查即可。解决办法是双方在STARTDT_CON后重置发送/接收计数器厂站程序必须实现这个逻辑。排查技巧把wireshark里过滤条件设为iec60870_104.i可以直接过滤I帧报文观察两次连接的第一个I帧N(S)是否为0。7.3 故障三k和w冲突导致死锁如果配置了w k接收方可能永远等不到第w个I帧才确认发送方又因为k窗口满而停止发送链路形成死锁。这种问题在报文上表现为发送方连续发到第k帧后停止接收方一个确认都没有双方就这么干等到t1超时。排查要点核对两侧的k/w配置确保k w且w至少为1。在国网、南网的入网检测中这个配置是必查项。7.4 故障四测试帧TESTFR无响应现象链路空闲时发送方发TESTFR_ACT后一直收不到TESTFR_CONt3超时后断开。可能原因对端程序的U帧处理逻辑有bug只处理I帧不处理U帧。对端处于忙状态来不及回TESTFR_CON但这种情况通常不应发生因为TESTFR_CON优先级很高。TCP连接虽然存在但对端进程假死。这种情况通过抓包可以清晰定位TESTFR_ACT发出后对端TCP层回了ACK但应用层始终无响应。这意味着TCP连接从内核层面是通的但应用进程已经卡死。处理方法是完善厂站程序的应用级看门狗。8. 参数测试验证方法怎么确认你的参数改对了8.1 用报文间隔和序号差值推算窗口占用改完参数后想验证k值是否真的生效可以在主站侧抓包观察连续发送的I帧数量和确认回的节奏。如果配置k12、w8正常稳定运行时抓包会看到发送方连续发8个I帧左右接收方回一个S帧确认因为w8触发然后发送方继续发形成一种“发8确认1”的节奏。如果看到发送方连续发到12帧还没等到确认且停顿下来那说明接收方的w配置大于12或者接收方的确认逻辑有延迟。这个现象是判断参数是否生效的直观依据。8.2 模拟丢包和延迟场景在有条件的测试环境里用tc命令模拟网络丢包和延迟验证参数在劣化通道下的表现。例如# 在Linux网卡上模拟10%丢包和200ms延迟 tc qdisc add dev eth0 root netem loss 10% delay 200ms此时观察主站和厂站的行为正常情况下TCP会重传丢掉的段104应用层因为收到TCP保证的有序数据不会感知到丢包如果丢包率过高TCP重传时间超过t2/t1链路上就会出现S帧延迟、I帧堆积进而触发t1断链。这种测试能帮你摸清t1、t3在当前网络质量下的裕度。8.3 批量接入压力测试模拟多个厂站同时上送全数据观察主站侧CPU占用、S帧发送频率、TCP接收队列积压情况。重点关注w值是否过大导致主站处理不过来S帧发送延迟、k值是否过小导致厂站数据拥塞厂站发送窗口经常满。这个测试在做主站系统投运前联调时非常有必要。9. 各厂家设备参数配置差异和处理心得国内主流厂站的104参数在默认值上基本遵循IEC 60870-5-104建议值但不同设备在参数可调范围和界面名称上差异很大厂家/设备参数名称习惯是否可调注意事项南瑞、南自等传统远动装置常直接叫“K值”“W值”超时叫“T1/T2/T3”通常可调但部分老固件仅支持默认值修改后必须重启通信进程不重启不生效部分进口保护装置叫“Maximum outstanding APDUs”“Acknowledge timeout”等范围有限需查英文手册国网入网设备一般做了本地化适配规约转换器如IEC 104转Modbus界面里有“窗口参数”分组一般可调确认配置下发后是否热生效有些需要重启服务虚拟厂站/仿真软件通常在配置文件或注册表灵活可调测试时注意与真实设备参数保持一致避免测试结果失真我的经验是动手改参数之前先看厂家说明书里的参数范围表。有的装置k值范围是1~15w范围是1~15且要求wk有的装置k值甚至支持到32767——但这么极端的大窗口在实际调度系统中没有意义反而会让故障恢复更慢。如果不是特殊原因优先保持默认值不要为了“提升性能”盲目加大。另外注意一个容易忽略的细节104主站和厂站各自维护独立的发送窗口和接收窗口k、w都是“本地参数”——发送方用k约束自己接收方用w约束自己。但两侧是否兼容取决于双方对“接收方允许的最大窗口”的协议宣示。实际工程中常见做法是双方把k设成一样的值w也设成一样的值避免出现“我以为你能收12个实际你只允许8个”这类隐性冲突。协议里还有一个点值得提104标准的第5.3节规定接收方应该能接收至少一个k值大小的未确认I帧序列。如果你的对端实现只缓冲了8帧而配置里写了k12发送方多发几帧时对端就丢包。排查时如果碰到“发送方没超窗口、接收方报序号丢失”的怪问题就该怀疑对端的接收缓冲区容量和k值不匹配。10. 一些实际工作中的补充经验再分享几个参数之外、但和滑动窗口息息相关的实践细节。第一TCP层的Nagle算法和延迟确认会严重影响104的实时性。TCP_NODELAY应该默认开启否则小报文S帧、U帧可能被延迟几十毫秒甚至更久才发送导致t2定时器频繁触发、链路表现“时快时慢”。排查时如果发现TCP报文有拼接现象优先检查这个。第二104链路建议使用独立的TCP端口不要在同一个TCP连接上混合传输其他业务。有些厂站为了省端口把104报文和MODBUS、日志报文混在一个连接里一旦其他业务流量大或发生阻塞104链路必然被拖累。这个在参数层面是调不回来的。第三主站接入多个厂站时每个TCP连接是独立的k/w不会互相干扰但TCP缓冲区大小、文件描述符数量、线程池大小要按“总接入数×每连接窗口大小”来估算。假设接入500个厂站每个连接最多12个未确认帧那么主站应用可能需要同时缓冲6000个报文的处理量内存和CPU都要提前做好冗余规划。最后说一个调优时的“量程”思路先满足可靠再追求效率。如果你不确定该不该调整参数先把所有参数设为协议默认值保证链路能稳定。然后在这个基础上用抓包统计链路的RTT、丢包率、应用处理耗时再针对性的调大t1、t2或增大k值。不要一上来就追求“窗口大、吞吐高”在电力调度这种对可靠性要求远高于吞吐量的领域稳定压倒一切。调参前想清楚你要解决的实际问题是超时断链、数据积压还是序号异常而不是为了调参而调参——这是我做了这么多年远动通信调试最想对刚接触104协议的朋友说的一句话。
返回列表