channel-tcp-client

介绍

通道服务名:tcp-client

工程名称:fox-edge-server-channel-tcp-client

说明:

tcp-client 通道服务,用于支持现场设备作为tcp-server通信的场景。

在现实项目中,有很多设备是基于TCP进行通信的,此时这些设备作为TCP的服务端,接受来自上位机的TCP连接。

当连接建立后,主要有两种通信模式,一种是主从半双工,一种是全双工方式

主从半双工 ,就是上位机主动对这些TCP设备发起连接后,上位机和设备之间,严格遵循一问一答的方式。 它们之间的一问一答,可以通过时序上的先后顺序,就能简单的判定。

全双工方式 ,就是上位机主动对这些TCP设备发起连接后,上位机和设备之间,并不遵循通过时序的问答来进行交互。 它们之间,完全是双向互相对等通信,各问各的,各答各的。它们并不存在先后关系,所以它们的互相操作,要靠彼此约 定的通信格式,以及通信内容来彼此识别。

针对这个业务场景,灵狐开发了 tcp-client 这种通道服务,来支持这两种场景。

进一步考虑到用户的现场设备可能有很多种类型,所以 tcp-client 支持为每一个通道,定义采用何种通信方式。

组网

源码

源码

说明

1、粘包/拆包

TCP是面向流的传输协议,但是上位机与设备的之间的交互,是一种彼此会话的动作。 此时会出现一种对应的现象,必然会出现一种所谓的 粘包 的现象。

所谓 粘包 ,设备向上位机发送了两组报文,结果上位机收到的是一组报文,而这组报文内容是两个组报文粘合在一起的内容。

例如:

设备->上位机:

AA AA 03 BB BB BB

AA AA 04 DD DD DD DD

结果上位机收到的是:

AA AA 03 BB BB BB AA AA 04 DD DD DD DD

为了解决这个问题,设备厂商约定,它们的报文是【AA AA】 + 【长度】+【数据】的格式,上位机收到一组粘包的数据后, 按这个格式进行拆解,就能够得到这真正的两组报文。

使用TCP协议传输数据的设备制造厂商,它们的设备协议上,都会定义有报头报长两种信息,来帮助分包。

如果它们的设备没有这种报头报长两这两个关键信息,别白费力气了,赶紧找设备厂商解决,或者直接更换设备厂商。

2、交互模式

设备制造厂商在设计它们的通信协议的时候,会有两种模式,一个是全双工模式,一种是半双工模式。

提醒:不会有哪混合两种的通信方式。如果说有,把你开发中遇到交互方面的时序问题,留给他去回答。

2.1、半双工模式

就是上位机主动对这些TCP设备发起连接后,上位机和设备之间,严格遵循一问一答的方式。

它们之间的一问一答,可以通过时序上的先后顺序,就能简单的判定。

在此种模式下,设备的身份可以通过设备的 IP:PORT 来进行身份识别。

该模式只支持 execute 操作。

2.2、全双工模式

就是上位机主动对这些TCP设备发起连接后,上位机和设备之间,并不遵循通过时序的问答来进行交互。

它们之间,完全是双向互相对等通信,各问各的,各答各的。它们的应答并不存在先后关系,所以它们的互相操作, 要靠彼此约定的通信格式,以及通信内容来彼此识别。

最常见的方式,有协议报文自带 身份特征 信息和 交互序号 ,通过这个特征,你就能知道回答你的设备 是具体的那一台设备,跟你进行问答的是哪一个问答。

注意:在这种模式下,需要使用到开发对应的JAR解码器,来帮助报文内容的识别。

该模式只支持 publishreport 操作。

3、技术方案

提供了加载解码器JAR的方式,来对报文的粘合包进行自动化拆包,对报文的碎包进行自动化的组包。

同样解码器JAR,也能对全双工方式下的身份识别特征进行内容识别。

4、开发范例

粘包/拆包的范例,开发者可以参考

源码

配置

tcp-client 通道服务的包括全局配置和通道配置

1、全局配置

jarFile:解码器文件

logger:是否打印后台日志

{
     "logger": false,
     "decoderList": [
          {
               "jarFile": "/jar/decoder/fox-edge-server-protocol-zktl-air6in1.v1.jar"
          },
          {
               "jarFile": "/jar/decoder/fox-edge-server-protocol-core.v1.jar"
          },
          {
               "jarFile": "/jar/decoder/fox-edge-server-protocol-zktl-air6in1.v1.jar"
          },
          {
               "jarFile": "/jar/decoder/fox-edge-server-protocol-zktl-air5in1.v1.jar"
          }
     ]
}

2、通道配置

host:设备IP

port:设备端口

mode:工作模式 full-duplex 或者 half-duplex

handler:进行报文拆解的解码器的JAVA代码,这个有具体某款设备的解码器信息,该信息有设备通信协议解码器的开发者 写的代码决定,该信息的填写方式由他提供。比如下文是air6in1开发者所提供的填写内容。

{
     "host": "127.0.0.1",
     "mode": "full-duplex",
     "port": 502,
     "handler": {
          "splitMessageHandler": "cn.foxtech.device.protocol.v1.zktl.air6in1.handler.ZktlSplitMessageHandler"
     }
}

解码器

如果是全双工模式(包括设备主动上报的工作模式),需要写解码器,此时需要看这段内容。

下面的内容,都是跟全双工方式相关的,如果你的是半双工方式设备,可以跳过这一节内容。

1、操作方法

全双工模式下的操作方法,只有单工的publishreport两种模式,没有主从半双工的execute模式。

这样设计的目的,是因为execute只适合一问一答式的传统自动化设备。

但是,对于很多会采用TCP的设备来说,它们的设计更多的是采用全双工的方式。

换句话说,在传输层面,上行和下行是彼此独立的,上行和下行,可以认为是两条各自独立的单向通道。

所以,tcp-server的操作方法,也跟着用publishreport来分别对应上行和下行数据的传输。

2、报文协议

TCP 是面向流的传输协议,想要在上面传输会话动作,必然会出现所谓的粘包问题。

所以,设备制造厂商,它们的设备协议上,会定义有报头报长两种信息,来帮助分包。

如果它们的设备没有这种报头报长两这两个关键信息,别白费力气了,赶紧找设备厂商解决,或者直接更换设备厂商。

以下以中科图灵的设备协议为范例:


某公司的安防设备,它的通信报文格式为
报头:4 字符, ‘2’ ’4’ ’2’ ’4’;
通信类型:1 字符
设备类型:1 字符
长度:2 字符
数据区:N字符
包尾:2 字符,’A’’ A’

报文范例:
2424 08 43 867572058700527 89861121245014174191 0058009b00b3006400b6019e110200 aa

2424是固定的报头,28是报长,这个适合就可以通过 这两个信息,对粘合成一长串的报文,进行准确的断句。

3、拆包接口

tcp-server提供了自动拆包的接口:cn.foxtech.device.protocol.v1.utils.netty.SplitMessageHandler
开发者应该写一个解码器,并派生一个子类,为tcp-server指出报头报长的特征,那么tcp-server在接收到数据流之后,
会使用SplitMessageHandler的派生类自动进行拆包操作。

你可以通过TCP工具给它发送测试字符串的报文进行效果测试:

24240843867572058700527898611212450141741910058009b00b3006400b6019e110200aa

设备层面的解码器会收到这个主动上报的报文。

操作

1、服务配置

tcp-client 启动的时候,会自动创建一个默认的全局配置

{
  "decoderList": [{
    "decoder": [{
      "jarFile": "\\jar\\decoder\\fox-edge-server-protocol-zktl-air6in1-1.0.2.jar"
    }],
    "keyHandler": "cn.foxtech.device.protocol.v1.zktl.air6in1.handler.ZktlServiceKeyHandler",
    "serverPort": 9301,
    "splitHandler": "cn.foxtech.device.protocol.v1.zktl.air6in1.handler.ZktlSplitMessageHandler"
  }, {
    "decoder": [{
      "jarFile": "\\jar\\decoder\\fox-edge-server-protocol-zktl-air5in1-1.0.2.jar"
    }],
    "keyHandler": "cn.foxtech.device.protocol.v1.zktl.air5in1.handler.ZktlServiceKeyHandler",
    "serverPort": 9302,
    "splitHandler": "cn.foxtech.device.protocol.v1.zktl.air5in1.handler.ZktlSplitMessageHandler"
  }]
}

2、通道管理

用户在通道界面创建一个tcp-server类型的通道之后,在通道上配置好身份特征特征,那么Fox-Edge就会遵循下列操作流程

【现场设备】《==TCP==》【通道服务】(tcp连接-身份特征-通道名)《==Channel==》【设备服务】

这样,上层应用就能够以channel的方式,进行跟远程的现场设备,基于tcp的方式进行交互操作了。

{
     "host": "127.0.0.1",
     "mode": "full-duplex",
     "port": 502,
     "handler": {
          "splitMessageHandler": "cn.foxtech.device.protocol.v1.zktl.air6in1.handler.ZktlSplitMessageHandler"
     }
}

3、注意

设备主动上报模式下,向等待设备主动发送一次身份特征报文后,此时才完整真正的设备身份认证。

然后,才能进行向设备主动执行 publish 操作