Ethernet/IP协议的数据帧格式或报文结构

1. Ethernet/IP的整体框架

Ethernet/IP 协议作为 CIP 的一种实现方式,其核心在于将高层的 CIP 数据封装到以太网的标准帧中进行传输。这种设计允许工业设备充分利用现有成熟的以太网基础设施来完成复杂的数据交互任务1

2. 以太网帧中的CIP数据封装

在一个典型的 Ethernet/IP 报文中,最外层遵循 IEEE 802.3 定义的传统以太网 II 帧格式。这包含了目的 MAC 地址、源 MAC 地址以及 EtherType 字段等内容。对于大多数 Ethernet/IP 应用来说,EtherType 被设置为 0x0800 表明后续负载是一个 IPv4 数据包;然而,在某些情况下也可能直接指定特殊的值如 0x88A4 来标识这是未经 IP 层处理的纯 CIP 流量4

  • 当前者情况发生时(即存在 IP 头部),紧接着的是标准 TCP 或 UDP 协议头部之后才是真正的应用层有效载荷区域——这里便是我们的主角:CIP Message Router 请求或者响应消息所在位置。

  • 如果后者被选用了,则意味着整个事务完全绕过了更高层次上的寻址机制而直奔主题去了!

3. 具体字段解析
(a)UDP无连接显式消息(CoE)
Field NameLength(Bytes)Description
Command Specific DataVariableContains additional parameters depending on command type
Session Handle4Identifies the session between client/server
Status4Indicates success/failure of operation
Sender Context8Optional field used by sender
Interface Handshake Protocol Version2Specifies version number
Option Flags2Reserved
Length2Total length of encapsulated data
Encapsulation Commands2Defines what action should be taken
DataVariableActual payload containing either request or reply

以上表格描述了一个典型UDP CoE PDU的基本组成部分及其含义解释

(b)TCP有连接隐式I/O流(IoC)

相比之下,TCP IoC 更加关注周期性的实时性要求较高的IO信号交换过程,因此它的PDU相对简单得多:

+-------------------+
| Common Packet Format|
+-------------------+
| Service Code       |
+-------------------+
| Request Path Size  |
+-------------------+
| Request Path       |
+-------------------+
| Additional Data    |
+-------------------+

此处,"Common Packet Format"再次扮演起承上启下的角色,它由固定长度的部分构成,用于指示接下来的服务类型编码等等信息

import socket
from struct import pack, unpack

def create_ethernet_ip_request(command_code, session_handle, status, context_bytes=b'\x00'*8, interface_version=1, option_flags=0):
    """
    构造一个基本的Ethernet/IP请求头
    
    参数:
        command_code (int): 封装命令代码.
        session_handle (int): 会话句柄数值.
        status (int): 状态字节通常设为零表示正常操作.
        context_bytes (bytes): 可选上下文字节数组,默认填充八个零字节.
        interface_version (int): 接口握手协议版本号,默认值为1.
        option_flags (int): 额外标志位,默认清零.

    返回:
        bytes: 组合后的完整请求二进制字符串.
    """

    # 打包各个字段成连续字节序列
    packed_data = b''.join([
        pack('!H', command_code),          # ! 表示网络序(Half-word unsigned short)
        pack('!L', session_handle),
        pack('!L', status),
        context_bytes,
        pack('!H', interface_version),
        pack('!H', option_flags)
    ])

    return packed_data


if __name__ == "__main__":
    req_header = create_ethernet_ip_request(0x6F, 123456789, 0)
    print(req_header.hex())

上述Python脚本演示了如何手动创建并发送一条简单的Ethernet/IP指令的方法之一2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值