总看到不少关于TCP三次握手和四次挥手的文章,一直一知半解,今天就打算通过实践的方式来巩固一下这方面的知识。
准备工作:
1. 下载NetAssist、Wireshark工具。
2. 准备两台电脑,一台作为TCP服务端,一台作为客户端
3. 配置好Wireshark,准备抓包

由于测试过程中,TCP客户端会需要反复断开连接,即端口会发生变化,所以在Wireshark抓包里,就按照TCP服务端的端口来过滤数据。
本文环境:
客户端IP:192.168.2.43
TCP服务端IP+端口:192.168.2.38:8080
两台电脑均为Windows系统。
Wireshark是运行在客户端电脑上。
实践流程:
按照以下顺序,依次关注客户端和服务端两边TCP网络连接的状态,同时分析传送报文的含义。
通过如下命令,来查看网络连接情况:
netstat -ano | findstr "8080"
1. 开启TCP服务端
2. TCP客户端连接服务端,IP错误
3. TCP客户端连接服务端,端口错误
4. TCP客户端与服务端连接成功
5. TCP客户端发消息
6. TCP服务端发消息
7. 更换消息,再一次重复5、6步骤
8. 断开TCP客户端
9. 断开TCP服务端
10. 重新开始1到7的步骤,将最后8、9步骤调换顺序
1. 开启TCP服务端:
TCP客户端无连接,服务端显示如下:
TCP 129.168.2.38:8080 0.0.0.0:0 LISTENING 16648
16648表示TCP服务的进程ID。

此时由于还没有连接建立,所以Wiershark里无数据的传输记录。
2. TCP客户端连接服务端,IP错误
通过抓包可看到,灰色行114358表明是客户端向错误的ip发出的请求数据包,后面黑色TCP Retransmission都代表连接失败后,再次重新发出连接的请求。

仔细留意,可以看到连接请求响应的数据里都带有RST的信号。
RST,英文Reset的缩写,即重置的意思。
关于哪些情形下会出现RST的信号,我们以后继续学习。
3. TCP客户端连接服务端,端口错误
这里拿端口8081测试,所以记得把Wireshark里数据过滤条件也相应地修改一下。

对比第2步骤的图,明显可以看到下面这个没有相应的数据包,但是重连尝试的次数,一样也是4次。
4. TCP客户端与服务端连接成功
这一步骤,也是我们经常提到的TCP连接需要遵循3次握手的规律所处于的步骤。
连接成功后,客户端端口显示为:53237
在客户端查看连接情况,如下所示:
TCP 192.168.2.43:53237 192.168.2.38:8080 ESTABLISHED 14748
在服务端查看连接情况,如下所示:
TCP 192.168.2.38:8080 192.168.2.43:53237 ESTABLISHED 16648
抓包显示,也如同3次握手,只显示了3条数据。

再结合网上这张图,我们加深一下理解。

开始客户端发了seq=x这个数据,服务端通过ack=x+1来告诉客户端:我收到你发的数据了。
同时服务端还另外带了seq=y这个数据,类似向客户端喊话:如果收到我的确认,麻烦回复一下哈。
最后客户端再次发送ack=y+1,向服务端发出确认:我知道你已经收到了。
需要注意的就是,客户端这边第二次发出的数据,属于确认消息,所以是基于第二步它所收到的数据上进行告知,即seq=y这个数据。
如此捋下来,就知道信号的含义了:
SYN代表数据的发送,ACK代表信息的确认
在上面抓包数据里,x为0,所以详细关系并没有上图那么清晰明了。
5. TCP客户端发消息

在TCP客户端发送Hello World,服务端数据日志窗口里,可以看到Hello World,即代表数据传输成功。
从下面的抓包记录可以看出,此时发送数据信号变为PSH,不再是建立连接阶段里的SYN信号。

关于报文的长度,日后分析。
6. TCP服务端发消息
从服务端发送Hello,Test(逗号是英文格式),两边连接状态没有任何变化。
如下红框是抓包数据记录。

(上面Hello,World为何长度为13,经过检查,是发送数据的时候,在末尾多输入了一个换行符)
7. 更换消息,再一次重复5、6步骤

经过梳理,可发现数据包发送有如下规律:
Ack的值 = 收到的Syn的值 + 数据的长度Len
数据包的Seq(无论PSH还是ACK) = 上一次反向传输中的Ack值
最后再按照下图,客户端与服务端各自发送了3笔数据。
服务端发送Hello,Test, 客户端发送Hello,World。

抓包显示如下:

圆框是客户端为数据发送方,矩形框是服务端为数据发送方。
关于seq值和ack值的规律,日后继续深究。
8. 断开TCP客户端
在客户端查看连接情况,如下所示:
TCP 192.168.2.43:53237 192.168.2.38:8080 TIME_WAIT 0
过几分钟之后,就消失了
在服务端直接就看不到连接了。
9. 断开TCP服务端
客户端连接立马消失,服务端则也是显示TIME_WAIT状态,几分钟后消失。

客户端会尝试用各种端口去重连,每个尝试,都会进行4次重复。