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地址)。每一层都会添加头部信息,接收方逐层解封装。
2.2 Socket建立流程:bind/listen/accept/connect
Socket是应用层与传输层之间的编程接口。在SECS/GEM中,设备通常作为服务器(被动方),主机作为客户端(主动方)。Socket通信的建立遵循经典的C/S模型。
2.2.1 服务端流程
- socket():创建套接字,指定协议族(AF_INET)、类型(SOCK_STREAM)和协议(TCP)。
- bind():将套接字绑定到本地IP地址和端口号。SECS/GEM默认端口号通常为5000或5001。
- listen():将套接字设为监听模式,指定最大等待连接数(backlog)。
- accept():阻塞等待客户端连接,返回一个新的套接字用于与客户端通信。
2.2.2 客户端流程
- socket():创建套接字。
- connect():向服务端的IP地址和端口发起连接请求。
常见异常:bind()失败通常因端口被占用;connect()超时可能因防火墙拦截或IP不可达;accept()返回错误可能因backlog队列溢出。
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(可能客户端异常或半连接攻击)。
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过多可能因短连接频繁创建,需调整系统参数。
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秒,应触发告警并尝试重建连接。