TCP/IP基础回顾:Socket通信原理、端口与连接、TCP三次握手与四次挥手、数据包结构

各位同学,咱们今天聊点“老本行”——TCP/IP。你可能会想:“这玩意儿我大学就学过,还用再讲?”

嗯,我在半导体设备现场摸爬滚打这么多年,发现一个规律:HSMS连不上的问题,十有八九是TCP/IP基础没吃透。不是协议本身多难,而是你排查时脑子里没有那张“数据包怎么走”的图。

所以这一章,咱们不背书,我带你从Socket通信原理开始,把三次握手、四次挥手、数据包结构这些硬骨头,用工程师的视角重新啃一遍。

2.1 Socket通信:说白了就是“两个程序打电话”

Socket是什么?我习惯把它理解成一个通信的“插座”。一端插在设备端(比如你的晶圆传输平台),另一端插在主机(比如MES系统),中间通过TCP/IP协议栈传数据。

核心概念:Socket = IP地址 + 端口号。IP地址找到哪台机器,端口号找到机器上的哪个进程。

在HSMS场景里,设备端通常作为客户端主动发起连接,主机作为服务器端监听端口。我见过不少新手把角色搞反,结果设备死活连不上主机——其实不是代码错了,是Socket角色没配对。

Socket通信的基本流程(以HSMS为例)

  1. 服务器端(主机):创建Socket → 绑定端口(比如5000) → 监听 → 接受连接
  2. 客户端(设备):创建Socket → 连接服务器IP+端口 → 发送数据
  3. 数据传输:双方通过已建立的连接读写数据
  4. 关闭连接:任意一方调用close()

避坑指南:我曾经遇到一个案例,设备端每次连接后都忘记关闭Socket,结果端口被占满,新连接全部失败。后来加了个超时关闭机制才解决。记住:Socket资源不是无限的。

2.2 端口与连接:别让端口号“打架”

端口号范围是0~65535。其中0~1023是知名端口,留给HTTP、FTP这些标准服务。HSMS通常用5000~9999之间的端口,具体看设备厂商定义。

端口范围 用途 HSMS相关说明
0~1023 知名端口(系统服务) 不要占用,否则可能冲突
1024~49151 注册端口(用户服务) HSMS常用区间,如5000、6000
49152~65535 动态/私有端口 临时连接使用,设备端自动分配

你想想看,如果设备端和主机端都用了同一个端口号,会发生什么?端口冲突。我在调试某款刻蚀设备时,就遇到过主机端端口被其他进程占用,导致HSMS连接一直超时。排查了半天,最后用netstat -ano一看,才发现是另一个测试程序占着端口没释放。

重要提醒:生产环境中,务必确保HSMS端口是独占的。不要跟其他服务共用端口,也不要让防火墙把端口给拦了。我曾经在客户现场,防火墙策略把5000端口封了,设备端连了三天都连不上——最后发现是IT部门“好心”做了安全加固。

2.3 TCP三次握手:为什么是三次?

TCP是面向连接的协议,通信前必须先建立连接。三次握手就是建立连接的过程。说白了,就是双方互相确认:“你准备好了吗?”“我准备好了!”“那咱们开始吧!”

我画了一张流程图,帮你把三次握手的过程刻在脑子里:

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 ✅ 连接建立成功,开始传输数据

三次握手的核心目的:同步双方的序列号。第一次握手,客户端告诉服务器“我要连你,我的初始序列号是x”;第二次握手,服务器回应“收到,我的初始序列号是y”;第三次握手,客户端确认“好的,开始传数据吧”。

为什么不是两次? 如果只有两次握手,服务器无法确认客户端是否收到了自己的SYN+ACK。万一丢包了,服务器会一直等客户端的数据,造成资源浪费。三次握手是最小可靠方案。

我在调试HSMS时,经常用Wireshark抓包看三次握手。如果只看到SYN没看到SYN+ACK,那基本是防火墙把包丢了,或者服务器端口没开。如果看到SYN+ACK但没看到最后的ACK,那可能是客户端网络有问题。

2.4 TCP四次挥手:好聚好散

通信结束后,需要断开连接。四次挥手就是“分手”的过程。为什么是四次?因为TCP是全双工的,双方都要独立关闭自己的通道。

TCP四次挥手流程图 TCP四次挥手流程 主动关闭方 被动关闭方 ① FIN=1, seq=u FIN_WAIT_1 ② ACK=1, seq=v, ack=u+1 CLOSE_WAIT FIN_WAIT_2 ③ FIN=1, seq=w LAST_ACK ④ ACK=1, seq=u+1, ack=w+1 TIME_WAIT CLOSED ⏳ TIME_WAIT:等待2MSL(约2分钟)后进入CLOSED 确保被动关闭方收到最后的ACK

四次挥手的关键点:

  • 第一次挥手:主动关闭方发送FIN,表示“我这边没数据要发了”
  • 第二次挥手:被动关闭方回复ACK,表示“收到,但我可能还有数据要发”
  • 第三次挥手:被动关闭方发送FIN,表示“我这边也发完了”
  • 第四次挥手:主动关闭方回复ACK,然后进入TIME_WAIT状态

注意TIME_WAIT:主动关闭方在发送第四次挥手后,不会立即关闭,而是进入TIME_WAIT状态,等待2MSL(约2分钟)。为什么?因为要确保被动关闭方收到了最后的ACK。如果ACK丢了,被动关闭方会重发FIN,主动关闭方还能再回应。

我在HSMS调试中遇到过一个问题:设备端频繁断开重连,导致主机端出现大量TIME_WAIT状态的连接,最终端口耗尽。解决方案是让设备端尽量作为主动关闭方,或者缩短TIME_WAIT时间(生产环境慎用)。

2.5 TCP数据包结构:看懂报文才能定位问题

TCP数据包(报文段)的结构,说白了就是一堆控制字段 + 数据。你不需要背下所有字段,但以下几个必须记住,因为排查HSMS问题时经常用到:

字段 长度 作用 排查要点
源端口 / 目的端口 各16位 标识通信进程 检查端口号是否匹配配置
序列号(seq) 32位 数据字节流的编号 乱序或丢包时检查seq是否连续
确认号(ack) 32位 期望收到的下一个seq 确认对方是否收到数据
标志位 9位 控制连接状态(SYN、ACK、FIN等) 看标志位就知道当前处于握手还是挥手阶段
窗口大小 16位 流量控制,告诉对方自己能收多少 窗口为0表示接收方缓冲区满了
校验和 16位 检测数据是否损坏 校验和错误说明链路层有问题

实战经验:有一次HSMS连接频繁超时,我抓包一看,发现窗口大小字段一直是0。原来是设备端的接收缓冲区设置太小,导致主机端发来的数据被“拒收”。调大缓冲区后,问题解决。

2.6 本章小结:一张图记住TCP/IP核心

好了,咱们把TCP/IP的核心知识点串起来。下面这张图,我建议你保存下来,以后排查HSMS连接问题时,先对照这张图过一遍:

TCP/IP核心知识体系 TCP/IP核心知识体系(HSMS视角) TCP/IP通信 Socket通信 IP+端口→进程通信 端口与连接 端口独占·避免冲突 三次握手 建立连接·同步序列号 四次挥手 断开连接·TIME_WAIT 💡 排查HSMS连接问题时,按这个顺序检查: Socket创建 → 端口可用 → 三次握手成功 → 数据传输 → 四次挥手正常 数据包结构:源端口·目的端口·seq·ack·标志位·窗口

这一章的内容,说白了就是为后续的HSMS连接调试打地基。你想想看,如果连TCP三次握手都看不懂,那HSMS的Select.req、Linktest.req这些消息交互就更难理解了。

我的建议:学完这一章,打开Wireshark抓一次真实的HSMS连接包。亲眼看看三次握手的SYN、SYN+ACK、ACK是怎么飞的,比看十遍书都管用。我在带新人时,第一件事就是让他们抓包看三次握手——看懂了,后面就好办了。