2. Socket通信基础:TCP/IP协议栈、Socket建立流程与三次握手/四次挥手

在SECS/GEM通信中,底层依赖TCP/IP协议栈与Socket接口实现设备间的可靠数据交换。理解Socket通信的建立与拆除机制,是诊断连接异常、超时与断连问题的前提。本节将系统梳理TCP/IP协议栈的分层模型、Socket编程的核心流程,以及TCP连接的三次握手与四次挥手过程。

2.1 TCP/IP协议栈分层模型

TCP/IP协议栈是互联网与工业以太网通信的基础。SECS/GEM通常运行在TCP/IP之上,其分层结构决定了数据封装与传输的路径。

层级 名称 典型协议/功能 SECS/GEM中的角色
4 应用层 HTTP, FTP, SECS-II, GEM 定义消息内容与状态机
3 传输层 TCP, UDP 提供可靠字节流(TCP)
2 网络层 IP, ICMP, ARP 寻址与路由
1 网络接口层 Ethernet, Wi-Fi, PPP 物理介质传输
诊断要点:SECS/GEM连接异常时,应首先确认传输层(TCP)状态,而非直接分析应用层消息。TCP连接未建立或异常断开,会导致上层HSMS通信失败。
协议栈数据封装过程:应用层数据 → TCP头部(端口号) → IP头部(IP地址) → 以太网帧(MAC地址)。每一层都会添加头部信息,接收方逐层解封装。
TCP/IP协议栈分层架构 TCP/IP协议栈分层与数据封装 第4层:应用层 SECS-II / GEM 消息 第3层:传输层 TCP头部(源端口 + 目的端口) 第2层:网络层 IP头部(源IP + 目的IP) 第1层:网络接口层 以太网帧头(源MAC + 目的MAC) 数据封装方向 说明:发送方逐层添加头部,接收方逐层剥离头部,最终还原应用层数据。

2.2 Socket建立流程:bind/listen/accept/connect

Socket是应用层与传输层之间的编程接口。在SECS/GEM中,设备通常作为服务器(被动方),主机作为客户端(主动方)。Socket通信的建立遵循经典的C/S模型。

2.2.1 服务端流程

  1. socket():创建套接字,指定协议族(AF_INET)、类型(SOCK_STREAM)和协议(TCP)。
  2. bind():将套接字绑定到本地IP地址和端口号。SECS/GEM默认端口号通常为5000或5001。
  3. listen():将套接字设为监听模式,指定最大等待连接数(backlog)。
  4. accept():阻塞等待客户端连接,返回一个新的套接字用于与客户端通信。

2.2.2 客户端流程

  1. socket():创建套接字。
  2. connect():向服务端的IP地址和端口发起连接请求。
常见异常:bind()失败通常因端口被占用;connect()超时可能因防火墙拦截或IP不可达;accept()返回错误可能因backlog队列溢出。
Socket建立流程 Socket建立流程(C/S模型) 服务端(Passive) socket() → 创建套接字 bind() → 绑定IP与端口 listen() → 进入监听状态 accept() → 等待客户端连接 建立连接,开始通信 客户端(Active) socket() → 创建套接字 connect() → 发起连接请求 建立连接,开始通信 三次握手 说明:服务端先启动并监听,客户端后发起connect()。accept()返回后,双方即可通过新套接字收发数据。 SECS/GEM中,设备通常作为服务端,主机作为客户端。

2.3 三次握手与四次挥手

TCP是面向连接的可靠传输协议。连接建立时通过三次握手同步序列号与窗口大小;连接关闭时通过四次挥手确保双方数据完整传输。

2.3.1 三次握手(建立连接)

步骤 发送方 报文 状态变化
1 客户端 → 服务端 SYN=1, seq=x 客户端进入 SYN_SENT
2 服务端 → 客户端 SYN=1, ACK=1, seq=y, ack=x+1 服务端进入 SYN_RCVD
3 客户端 → 服务端 ACK=1, seq=x+1, ack=y+1 双方进入 ESTABLISHED
诊断价值:如果连接停留在 SYN_SENT 状态,说明服务端未响应(可能端口未监听或防火墙丢弃SYN包);如果停留在 SYN_RCVD,说明客户端未回复ACK(可能客户端异常或半连接攻击)。
TCP三次握手 TCP三次握手流程 客户端 服务端 CLOSED LISTEN ① SYN=1, seq=x SYN_SENT ② SYN=1, ACK=1, seq=y, ack=x+1 SYN_RCVD ③ ACK=1, seq=x+1, ack=y+1 ESTABLISHED ESTABLISHED 说明:三次握手完成后,双方进入ESTABLISHED状态,可以开始传输SECS/GEM数据。

2.3.2 四次挥手(关闭连接)

步骤 发送方 报文 状态变化
1 主动方 → 被动方 FIN=1, seq=u 主动方进入 FIN_WAIT_1
2 被动方 → 主动方 ACK=1, seq=v, ack=u+1 被动方进入 CLOSE_WAIT,主动方进入 FIN_WAIT_2
3 被动方 → 主动方 FIN=1, ACK=1, seq=w, ack=u+1 被动方进入 LAST_ACK
4 主动方 → 被动方 ACK=1, seq=u+1, ack=w+1 主动方进入 TIME_WAIT,被动方进入 CLOSED
异常诊断:如果连接长时间处于 CLOSE_WAIT 状态,说明被动方应用未调用close(),导致资源泄漏;TIME_WAIT过多可能因短连接频繁创建,需调整系统参数。
TCP四次挥手 TCP四次挥手流程 主动关闭方 被动关闭方 ① FIN=1, seq=u FIN_WAIT_1 ② ACK=1, seq=v, ack=u+1 CLOSE_WAIT FIN_WAIT_2 ③ FIN=1, ACK=1, seq=w, ack=u+1 LAST_ACK ④ ACK=1, seq=u+1, ack=w+1 TIME_WAIT CLOSED 说明:主动方在TIME_WAIT状态等待2MSL(约2分钟),确保被动方收到最后一个ACK。 SECS/GEM中,异常断连常导致连接处于半关闭状态,需通过心跳检测恢复。

2.4 Socket状态与SECS/GEM连接诊断的关联

在Linux系统中,可以使用 netstat -anp | grep :5000 或 ss -tunap 查看Socket状态。以下状态与SECS/GEM连接异常直接相关:

  • LISTEN:服务端正常监听,但无客户端连接。若SECS/GEM设备未进入监听状态,需检查bind()是否成功。
  • SYN_SENT:客户端已发送SYN但未收到SYN+ACK。可能原因:服务端未启动、防火墙拦截、网络不可达。
  • ESTABLISHED:连接正常建立。若SECS/GEM通信异常但状态为ESTABLISHED,需检查应用层心跳或HSMS消息超时。
  • CLOSE_WAIT:被动方收到FIN但未调用close()。常见于程序未正确处理连接关闭事件,导致资源泄漏。
  • TIME_WAIT:主动方等待2MSL。大量TIME_WAIT可能耗尽端口资源,需优化连接复用策略。
诊断命令示例:
# 查看所有TCP连接状态
netstat -ant | grep 5000

# 查看特定进程的Socket状态
ss -tunap | grep gem

# 统计各状态连接数
netstat -ant | awk '{print $6}' | sort | uniq -c
最佳实践:在SECS/GEM设备端部署定时监控脚本,每30秒检查一次Socket状态。若发现CLOSE_WAIT或SYN_SENT持续超过10秒,应触发告警并尝试重建连接。