news 2026/9/21 23:43:29

以太网103规约调试指南:从TCP建链到总召唤全解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
以太网103规约调试指南:从TCP建链到总召唤全解析

干了这么多年变电站的通信调试,我越来越觉得,很多工程问题不是出在规约本身,而是出在“你以为你懂规约”。就拿南自系保护装置的以太网103来说,不少新手拿着串口103的配置思路去调网络版,结果TCP连接明明建立了,总召唤就是没有响应,现场一夜都别想好过。

实际上,以太网103和串口103的底层逻辑已经变了。它不再是简单的“波特率、奇偶校验、站地址”三件套配置,而是一套由TCP/IP负责传输、FT1.2帧负责组包、ASDU负责业务语义的分层协议栈。这篇内容我从主站和子站的连接建立、报文字节结构、总召唤流程到现场高频坑位完整拆一遍,希望能帮到正在调保护装置接口的自动化工程师,也让刚想入门的同学知道这类规约到底是怎么跑起来的。

1. 103规约为什么会被搬上以太网:它本来不是写给网线用的

1.1 103的“串口基因”

IEC 60870-5-103规约诞生的年代,变电站站控层的主流物理通道还是RS-232和RS-485,链路层用FT1.2帧格式,主站与子站就是典型的一主多从或者点对点连接。这条规约的主要任务是让监控后台能拿到保护装置的遥信、遥测、SOE事件、故障录波信息,同时下发遥控和定值操作命令。由于它面向的是保护设备,所以对报文中的“时间标签”和“事件顺序”要求特别严格,这也是103和电力系统里很多其他规约最大的区别之一。

有意思的是,103虽然定位在“保护设备通信”,但它的链路层沿用了IEC 60870-5-101最早的一套框架。这就导致大家在串口时代调试103时,核心精力都放在串口参数上:波特率对不对、校验位是什么、从站地址是否越界、主站轮询周期合不合理。当时的工程经验是“地址对了一切都好说”,这句话放到今天的以太网103场景里,只对了一半。

1.2 站控层以太网化之后,为什么还要沿用103

新一代变电站站控层早就全面以太网化了,保护装置也普遍配备百兆或千兆电口。理论上大家可以直接上IEC 61850,但问题在于大量的存量装置、第三方监控后台、保信子站,短时间内不可能全部迁移。为了让老设备和新网络共生,最现实的办法就是做一套“以太网版的103”:

  • 保留原103协议的应用层语义和ASDU格式,降低软件改动量。
  • 将链路层的传输通道从串口替换为TCP/IP。
  • 去除串口链路特有的物理层握手和奇偶校验机制。

换句话讲,你就把原来串口线上跑的字节流,原封不动地塞进一个TCP连接里。代码改起来简单,但这背后引发了一个很隐蔽的问题:串口和网口对“帧边界”的定义不同。串口上一帧数据从启动字符到结束字符有明确的停止位和空闲间隔,TCP则是一个无边界的字节流,帧边界必须靠应用层自己识别。这也是后面很多通信故障的真正源头。

1.3 南自系设备的以太网103实现面貌

南自系(包括早期南自院的PSL系列保护、后来整合的各类测控装置)在以太网103的实现上,基本思路是:保护装置作为TCP服务端,在某个固定端口上监听;监控后台或保信子站作为TCP客户端主动建链。连接建立后,装置侧会周期发送链路测试帧或者等待主站发起总召唤,应用层报文依然维持103那套ASDU结构。

但这里要特别提醒:以太网103至今没有一个像IEC 61850那样严格的国际标准来约束厂商细节。同一个“以太网103”的名字下,不同厂家的端口号、控制域定义、公共地址编码方式,甚至是否保留校验和都可能不同。所以做现场调试之前,第一件事不是打开配置工具乱填IP,而是找厂家要对应版本的规约说明,搞清楚它到底属于“完整FT1.2帧包裹”还是“只传ASDU裸数据”。

这部分决定了后续所有调试思路的方向。我见过太多人先入为主觉得“规约都差不多”,结果把一个TCP粘包问题误判成公共地址错误,折腾一晚上。

2. 建链与保活:主站和子站是怎么把TCP会话维持住的

2.1 谁是Server,谁是Client,方向错了连不上

以太网103最常见的组网方式,是保护装置固定监听一个服务端口,主站侧软件(监控后台、保信子站、规约转换器)主动去连它。也就是说,每个保护装置是一个TCP Server,IP地址是唯一的,砖头一样放在那里等人来连。

不过我也见过反过来的场景。有些厂商的通信管理机或者保信子站希望自己作为Server,让下面的保护装置按预设的IP和端口主动上连。这种方案的好处是主站侧不需要维护庞大的设备接入状态,装置挂了重新上电还会主动重连,但也带来了配置和管理上的复杂性。

现场调试的第一步永远是确认连接方向。你可以用netstat或者wireshark抓包观察,看SYN包到底是从主站发出还是从子站发出。很多“连不上”的问题,不是IP不通,也不是网线没插好,而是两端都在等对方先说话。

2.2 连接建立后的心跳机制:有连接不等于活着

TCP连接建立起来之后,两边并不会立刻开始传业务数据。主站一般会先发一个链路测试帧(有的实现是总召唤,有的实现是控制域里特定功能码的测试命令),试探子站是否在线。子站收到后返回一个确认帧。这个频率通常在5秒到30秒之间,不同厂家的缺省值不一样。

如果子站连续多次没有响应,主站会判定链路中断,然后进入重连状态,不断尝试重新发起TCP连接。这里有个经验值:主站侧的超时时间一般设置为发送周期的2到3倍,太短容易被网络抖动误伤,太长又会拖慢故障发现速度。我之前处理过一次现场频繁掉线的问题,最后发现是子站程序里有一个看门狗,每隔30秒才发一次链路测试帧,而主站侧8秒没收到数据就判断链路断了,两边节奏完全不在一个频道上。步调不一致导致的“假死”局面,非抓包根本看不出来。

2.3 端口、公共地址和设备IP之间的关系

很多新手会把“端口”和“公共地址”搞混。端口是TCP传输层的概念,它决定数据包交给哪一个应用程序处理;公共地址在103规约里是应用层的概念,出现在ASDU字段中,用来标识不同的子站或装置。IP负责在网络层找设备,端口负责在设备上找服务进程,公共地址负责在装置内部确认“这批数据是给谁的”。

一个保护装置可能配置了多个网络口,每个网络口上跑着不同的规约服务,对应不同的TCP端口。比如用于监控后台的以太网103监听在2404,用于保信子站的扩展103监听在另一个高端口。端口号不同,应用层解析逻辑完全不一样。所以在配置主站时,不仅要把子站的IP填对,还要把端口填对,同时把ASDU里的公共地址设成和装置一致。三者缺一不可。

从实际工程看,很多老装置的公共地址支持范围是1到254,和串口时代的地址范围一脉相承。但网络化之后,IP本身就承担了寻址功能,公共地址渐渐变成一个“合法性校验项”,不再承担路由选择。有的实现甚至不检查它,只要TCP连接在,ASDU里的公共地址随便填也能通信。这种兼容性的差异,恰恰是调试中最坑的地方。

3. 报文结构拆解:从0x68到ASDU,一帧数据到底怎么组装出来的

3.1 典型的可变长帧格式长什么样

以太网103虽然在物理层改成了TCP/IP,但很多实现依然沿用了FT1.2风格的可变长帧骨架。一个典型的报文是这样组成的:

  • 启动字符 0x68
  • 长度标识符L、L
  • 启动字符 0x68(重复)
  • 控制域C
  • 公共地址A
  • 应用服务数据单元ASDU
  • 校验和(部分以太网实现会省略)
  • 结束字符 0x16

长度标识符L表示从控制域开始到ASDU结束的字节总数,通常占两个相同字节。这是为了在串口帧中出现连续0x68时也能正确识别帧边界。到了以太网上,由于TCP是流式传输,粘包和半包问题比串口严重得多,接收方必须靠长度L来精确截取一帧,否则解析就会错位。这部分是实现主站解析软件时的核心逻辑,很多人调试“为什么数据乱码”到最后,发现根本不是编码问题,而是按固定偏移量读帧,没等长度字段就硬切,一帧错,帧帧错。

3.2 控制域里的门道:谁在说话,这一帧是干嘛的

控制域在103链路层里是最容易忽略、但又最关键的一个字节。它的位定义从高到低包括方向位DIR、启动标志位PRM、帧计数位FCB/FCV,以及一组功能码。方向位为0表示主站到子站方向,为1表示子站到主站方向。PRM为1表示这一帧是启动侧的请求,为0表示是从动侧的应答。

常见的功能码逻辑:

  • 主站发送用户数据(带请求确认)时,功能码通常为3。
  • 子站正确接收并校验无误后,回应答帧,功能码为0或1。
  • 子站主动上报事件数据时,功能码为8或9之类,表示“这是响应数据”。

这里不打算让大家死记硬背每一个二进制位,因为在以太网103实现里,控制域的细节实在太杂,有的厂家的FCB位随帧交替从0变成1,有的则完全固定不变化。真正有效的调试办法,是找到一套抓包工具,先把主站侧发出的控制域和子站侧返回的控制域各抓几组,对照着看方向位和功能码的变化规律。只要回包控制域的PRM位为0,就能确认它是子站的应答,再结合ASDU的内容判断这一帧的业务类型。

3.3 ASDU字段:真正的业务数据在这

应用服务数据单元(ASDU)是整个报文的灵魂,它承载着103规约的具体业务语义。ASDU一般由以下几个字段构成:

  • 类型标识:用1个字节表示数据类别,比如总召唤、单点遥信、带时标的双点遥信、测量值、时钟同步、遥控命令等。
  • 可变结构限定词(VSQ):表示当前ASDU里包含的信息对象个数,以及这些信息对象是连续排列还是离散排列。
  • 传送原因(COT):表示这一帧的触发原因,最典型的是6(激活)、7(激活确认)、10(激活终止)、3(突发事件)等。
  • 公共地址:用于标识子站地址。
  • 信息体地址:表示具体的数据点地址,比如某个遥信点号、某个遥测点号。
  • 信息体数据:根据类型标识的不同,可能是单点状态值、双点状态值、浮点测量值、时标等。

这里面的难点在于,103规约的ASDU很多是从IEC 60870-5-101/104体系里继承过来的,类型标识在不同厂家的产品中可能有复用和扩展。例如带时标的单点信息在101体系里常见的类型标识为30,不少以太网103实现也沿用了这个编号。但不要默认所有厂家都一致,还是要回到装置的规约手册里去核对。

3.4 实例拆解:一帧总召唤请求的字节级读法

下面我们拿一帧典型的“主站发起总召唤”报文来做个逐字节分解,这里的例子按通用FT1.2帧加常见的101/104公共ASDU风格来展示:

68 0B 0B 68 53 01 64 01 06 00 01 00 00 00 00 30 16

逐字节解释:

  • 68:启动字符。
  • 0B 0B:从控制域到ASDU结束一共11个字节。
  • 68:第二个启动字符。
  • 53:控制域,方向位为0表示主站发送,PRM为1,功能码为3,代表发送用户数据并期望确认。
  • 01:公共地址,对应子站地址1。
  • 64:类型标识,十进制100,总召唤命令。
  • 01:VSQ,表示只有一个信息对象。
  • 06 00:传送原因,低字节在前,表示“激活”。
  • 01 00:公共地址,低字节在前,和前面控制域后的地址口径一致。
  • 00 00 00:信息体地址,全0表示对所有信息点进行总召唤。
  • 30:校验和。
  • 16:结束字符。

这一帧看着简单,但它在整个通信流程中非常重要。子站收到这一帧之后,如果校验通过、公共地址匹配,才会进入总召唤的数据上送流程。如果这里任何一个字段不匹配,子站就可能悄无声息地把这帧丢掉,主站侧的表现就是“我发了总召唤,它不回应”。

4. 从总召唤到遥控:主站与子站之间的典型交互流程

4.1 主站启动后的第一件事:先建立上下文

TCP连接建立之后,主站不会立刻收数据,而是先做设备上线初始化。大多数主站程序会先发一条链路复位或者链路测试命令,再发送总召唤。这么做的目的,是让子站进入一个已知的初始状态,清空之前可能残留的缓存或者中间态。

有些主站还会在总召唤之前先做一次时钟同步,确保事件时标的基准一致。因为103规约对SOE事件的时标要求很严格,时钟不同步会导致故障分析时的顺序错乱,后期排查会很头疼。

初始化顺序在不同厂家产品里略有差异,但基本的逻辑是:链路确认、时钟同步、总召唤、等待全数据、之后进入周期刷新和事件监听。

4.2 总召唤的完整交互过程

总召唤不是一个一来一回的过程,而是三个阶段:

  1. 主站发送总召唤请求,传送原因置为“激活”(6)。
  2. 子站校验通过后,先回一帧“激活确认”(7),表示我收到并接受总召唤。
  3. 子站接着把当前所有信息点数据按地址顺序逐一上送,这些数据帧的传送原因是“响应总召唤”(20)。
  4. 所有数据发送完毕后,子站再发一帧“激活终止”(10),告诉主站“所有数据都发完了”。

这里要特别注意第4步。主站软件通常是以收到“激活终止”来判断一轮总召唤是否完成的。如果子站数据很多,上送过程可能持续几秒甚至更长;如果中途网络丢包导致“激活终止”丢了,主站会认为总召唤尚未完成,直接超时。这也是103以太网通信里最常见的故障现象之一。

4.3 周期遥测和突发变位:两种完全不同的数据路径

总召唤完成之后,系统进入正常运行状态。遥测数据一般按照主站配置的周期进行周期上送,例如2秒或5秒一次。这部分数据的传送原因通常是“周期”,个别实现也直接使用循环数据类ASDU。

遥信变位和SOE事件则属于突发路径。子站检测到开关变位,会主动向主站推送带时标的事件报文,传送原因一般置为“突发”。这类报文的优先级高于周期遥测,如果多个事件同时发生,子站会按内部优先级排队上送。

这里有一个工程经验:如果子站在同一时刻产生了大量SOE事件,以太网103实现又采用的是独立TCP连接,突发流量可能会挤压正常的总召唤通道。我曾经在故障录波调阅时发现,主站那边数据刷得飞快,但总召唤始终完不成,最后查出是子站把事件上送和总召唤响应都放在同一条连接上,又没有做优先级调度,大量事件把总召唤的数据帧挤在后面了。

4.4 时钟同步和遥控命令的特殊性

时钟同步在103规约里不是随便发一帧就完事的。主站发送时钟同步命令后,子站不仅要把本地时钟设置过去,还要记录命令的发出时间,以便计算通道延时。部分实现中,子站还会在确认帧里带回时间戳,让主站进一步校准。

遥控命令则更严格。常规做法是分选程和执行两步:

  1. 主站下发“遥控预置”(选择)命令,传送原因置为激活。
  2. 子站校验该点位是否可遥控、是否匹配,然后返回“激活确认”。
  3. 主站在规定时间内下发“遥控执行”命令,子站输出执行,返回执行确认。
  4. 如果超时未收到执行命令,预置状态自动撤销。

如果子站返回的是“未知类型标识”或“未知信息体地址”,说明主站下发的遥控点号和装置内部定义不一致,或者是公共地址不匹配。这种问题通常在调试阶段就能暴露,但有些工程在系统未送电时只测试了遥信遥测,等真正需要遥控断路器的时候才发现点位没映射对,那就会非常被动。

4.5 多主站访问时的地址隔离

保护装置一般不只被一个主站连接,尤其是保信子站和监控后台可能同时需要访问。多个主站同时连接同一台装置时,如果装置在TCP层只允许一条连接,后来的主站会被拒之门外;如果允许多条连接,则需要考虑总线召唤是否互相干扰。

有些装置内部对每个TCP连接维护独立的总召唤状态,有些则是全局唯一的。如果是全局唯一状态,一个主站发起总召唤,另一个主站也在等总召唤完成,就会有一方一直等不到数据。我在现场碰到过这种场景:后台监控先发起总召唤,保信主站随后也发起总召唤,结果其中一侧老是不出数据。后来我们把两侧的轮询周期错开,问题才消失。

5. 现场最常踩的五个坑:从现象到排查思路

5.1 TCP连接一直建立不起来

现象:主站日志显示到子站的连接超时,TCP重传一直持续。

排查链路:

  • 先ping子站IP,不通就是物理链路问题,换网线、查交换机端口、查VLAN。
  • 通了但还是连不上,就用telnet测试子站端口是否开放。
  • 端口不通时登录子站后台,查规约服务进程是否启用,监听端口是否和主站配置一致。
  • 如果子站和主站之间隔了防火墙,还要确认放行策略。

这个坑一般不是难在技术,而是难在沟通。变电站调试时,装置物理端口和逻辑端口由不同专业人员管理,主站侧配的是2404,装置侧开的却是2405,两边都觉得自己没错。

5.2 TCP能建立,但总召唤发出去毫无回应

这是最隐蔽的一类问题。连接建立成功,说明网络层没问题,但子站对应用层报文“不感冒”,主要原因有三个:

  • ASDU里的公共地址和装置配置不一致,子站把帧校验后直接丢弃。
  • 类型标识或传送原因不被子站支持,或者使用的是厂家私有的扩展类型。
  • 控制域里的PRM、FCB位判断异常,子站不知道这是发给自己的请求。

排查方法很简单,用抓包工具把主站发出的那帧总召唤请求解析出来,和子站规约说明书里的定义逐字节比对。不要靠猜,直接看字节最靠谱。

5.3 数据大部分正常,但总是隔一段时间掉线又自恢复

现象:监控画面数据中断几十秒,然后又恢复正常,循环反复。

这类问题多数不在规约逻辑,而在TCP层面的连接管理。常见原因:

  • 子站在一段时间内没有收到任何应用层报文,主动关闭了连接。
  • 主站侧虽然认为连接还活着,但中间的网络设备(比如交换机端口、串口服务器)因为空闲超时把连接回收了。
  • 子站程序有内存缓冲溢出,长时间运行后进程卡死,看门狗复位后连接重来。

遇到这种情况,光调规约参数是没用的。先看两端日志里的断开时间点,再往前倒推网络空闲时间,把心跳周期调小或者缩短链路测试帧间隔,一般来说能解决大部分“隔段时间掉线”的诡异问题。

5.4 遥控命令发出后子站无动作,但遥信遥测都正常

现象:主站下发遥控预置,界面提示成功,但装置没有任何出口动作。

这类问题通常不是网络层,而是应用层映射。需要检查四件事:

  1. 主站配置里遥控对象对应的信息体地址是否和装置定义一致。
  2. 遥控选择的控制模式是单点还是双点,是否和装置侧匹配。
  3. 装置侧是否配置了遥控出口软压板,或者硬压板未投入。
  4. 多主站场景下,另一个主站是否有闭锁控制功能。

曾经有个现场,主站和装置在纸面上点表完全一致,遥控预置也返回了确认,但出口始终不动作,最后发现装置内还有一个“就地/远方”切换把手,当时处于就地位置。这种问题跟规约一点关系没有,但通信调试人员往往要陪到最后一刻。

5.5 抓包时数据正常,不在抓包时就有问题

这个现象听起来很玄学,但原理很简单:抓包工具本身影响了通信时序。wireshark或tcpdump在抓包时会给系统带来额外的CPU和内存负载,一些处理能力较弱的装置,或者主站侧规约解析程序线程比较脆弱的场景,本身已经处于临界状态,抓包只是压垮它的最后一根稻草。

另一个可能原因是在抓包过程中,主站侧的接收缓冲被暂时撑大,粘包半包问题被掩盖,误以为是网络原因导致的数据丢失。如果排除完所有逻辑和配置问题后,只在抓包时正常,那就要关注代码层面是否有缓冲区溢出、线程同步和内存竞争的问题。

写在最后的一点经验

这些年在103和104规约上踩过的坑,让我养成一个习惯:不论厂家兼容性有多好,配置完第一件事永远是抓一包原始报文,从头到尾按字节读一遍。不要急着点“连接”,不要急着看画面,先把链路层的帧和ASDU字段读懂,再去调业务逻辑。

还有个小技巧:如果现场允许,尽量在主站和子站之间加一台镜像交换机,把长期抓包变成常态。很多规约排查的难点不是问题本身,而是“问题发生时你恰好没看到”。有了连续抓包数据,很多偶发掉线、总召唤超时的问题,都能在事后翻报文时找到决定性的证据。做电力通信调试这行,耐心比技术更贵重,规约本身不复杂,复杂的是它周围那一圈千奇百怪的现实条件。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/21 23:24:38

交换芯片数据通路四大架构:Crossbar/VOQ/Shared Buffer/Cell Fabric工程权衡

1. 项目概述:为什么今天还要深挖交换芯片的“数据通路”?如果你在数据中心网络设备厂商做FPGA逻辑设计,或者在自研智能网卡、DPU的团队里负责流量调度模块,又或者正为下一代AI集群的无损网络架构做选型评估——那你大概率已经不止…

作者头像 李华
网站建设 2026/9/21 23:23:57

Python模块化编程:if __name__ == ‘__main__‘原理与实践

1. 为什么需要理解if __name__ __main__?第一次看到这行代码时,我也觉得它像某种神秘的仪式咒语。直到有次把脚本当模块导入时,整个程序突然不受控制地自动执行,我才明白它的重要性。这行代码实际上是Python模块化编程的基石&…

作者头像 李华
网站建设 2026/9/21 23:19:03

在 VSCode 上如何修改 json 配置文件,从而构建调试 C/C++ 项目

本文介绍如何通过更改配置文件,从而在 VSCode 上构建调试 C/C 项目。 能够解决的一些问题:头文件未包含而导致的未定义;头文件未能被识别而显示的提示错误等问题。 一、基本设置 vscode 上调试构建 c/cpp 项目都是基于这个拓展包,…

作者头像 李华