# 前言
前段时间在研究 IEC 60870-5-104规约,是一个广泛应用于电力、城市轨道交通等行业的国际标准。一般的使用场景是这样的:
主站和RTU之间使用 IEC 60870-5-104 规约进行通信,采用网络传输层的可靠传输协议TCP。主站和从站处于同一局域网。主站(控制侧)为TCP客户端,RTU(被控制端)为服务器端,即主站主动进行TCP连接,而RTU被动响应TCP连接。
# 需求
现应客户需求,RTU即服务器端放在局域网内,而主站即客户端要放在公网上。这样就存在一个问题,处在公网的客户端无法主动连接处于内网的服务器端(局域网IP的限制)。
# 引导
客户在IEC104使用方面有更丰富的经验,给我了点提示,让RTU先以客户端的身份去主动连接处在公网的服务器端(这时主站那边也不在担任客户端的角色的,因为它等待着被RTU连接,转而担任服务器端的角色),然后服务器端再通过这个连接,去继续IEC104规约的通信。
# 实现
只改了一行代码:Socket替换。
原始RTU代码(等待客户端连接部分)
SocketServerSocket_accept(ServerSocket self){int fd;Socket conSocket = NULL;fd = accept(self->fd, NULL, NULL );if (fd >= 0) {conSocket = TcpSocket_create();conSocket->fd = fd;activateTcpNoDelay(conSocket);}return conSocket;}
代码修改(Socket替换)
SocketServerSocket_accept(ServerSocket self){int fd;Socket conSocket = NULL;// fd = accept(self->fd, NULL, NULL );fd = sockfd;// sockfd为上一步RTU作为客户端客户端连接公网服务器的socket,// 直接将此socket当作是从accept分配的socket,// 服务端(公网TCP服务端)和服务端(局域网IEC104服务端)就能够// 通过此socket进行互相通信了。if (fd >= 0) {conSocket = TcpSocket_create();conSocket->fd = fd;activateTcpNoDelay(conSocket);}return conSocket;}
# 服务端和服务端通信
以上,利用TCP客户端的通信套接字,充当IEC104 Server部分通信套接字,从而达到服务端和服务端通信的目的。