使用WireShark对TCP三次握手进行分析
打开wireshark对某个ip查看tcp握手的过程
命令过滤tcp标志位syn值为1 和 tcp seq序列号值为1
(ip.addr == <本地ip> and tcp.flags.syn == 1 and ip.addr == <远程ip>
and tcp) or (ip.addr == <本地ip> and ip.addr == <远程ip> and tcp.seq == 1)
跟踪发现432518 432519 432520为TCP对目标ip进行三次握手的信息
第一次握手
- 客户端向服务端发送 标志位 SYN (SYN_SENT)= 1
- 序列号 Sequence Number(X) = 0
- 确认序列号 Acknowledgment = 0
第二次握手
- 服务端收到客户端的 标志位 SYN (SYN_SENT) = 1 知道了要与当前客户端建立tcp通信
- 服务端标志位 SYN(SYN_RCVD) = 1, ACK = 1
- 序列号 Sequence Number(Y) = 0
- 确认序列号 Acknowledgment (客户端序列号的X + 1 = 0 + 1) = 1
第三次握手
- 客户端收到服务端发来的 SYN(SYN_RCVD) + ACK + (上图)确认序列号为 X + 1 = 0 + 1 = 1 ,这三个数据确认正确则向服务端发送三次握手最终数据
- 客户端标志位ACK = 1
- 客户端序列号 Sequence Number (客户端第一次发送时的序列号X + 1) = 0 + 1 = 1
- 确认序列号 Acknowledgment (服务端发送的序列号Y + 1 = 0 + 1) = 1
至此,tcp三次握手结束
Q&A
根据文章解读
Sequence number \ Acknowledgment number \ Flags ACK(Acknowledgment) 有啥区别哇
Sequence number 是TCP会话两侧维护的一组32位序列号,用于跟踪已发送的数据量,这个序列号会包含在每个传输的数据包中,并由另一方的确认号(Acknowledgment number)进行确认,而且wireshark标记的Sequence number是一个相对数字,具体的Sequence number可以这样查看
0xC7DDD991拆成二进制一共32位的二进制,十六进制一位代表4个二进制位,一共八个十六进制位,那么一共就是32个二进制位
TCP Flags ACK标志位解读
引用以下stackoverflow上面的高赞回答
正在发送中的数据包的标志位都会设置ACK的值为1,可以通过wireshark跟踪以建立的tcp连接,在相互发送/接受数据包时,都会设置标志位ACK的值为1
为啥TCP就一定需要三次握手啊,两次,四次不行吗?
引用stackoverflow上的高赞回答
tcp基于双向传输,最少的双向建立会话次数为3
客户端与服务端都需要追踪一个Seq来持续收发数据包
1. 客户端需要初始化一个客户端Seq数字(X)然后同步给服务端
2. 服务端收到客户端发来的Seq然后表示我接收接下来客户端Seq+1
3. 服务端同步自己的Seq(Y)发送给客户端
4. 客户端收到服务端发来的服务端Seq,然后客户端表示我准备接收接下来服务端Seq + 1
上述步骤移除一步则tcp不能保证两端都能传输(从而导致只有一段的TCP状态为ESTABLISH,通常建立tcp连接后,应该客户端本地占用一个端口与服务端占用的端口建立会话(双方监听端口对应tcp状态都为ESTABLISH),只有一端建立会话,只有此端能发数据,另外一端只能收数据),而且,具体抓包发现2和3步骤,服务端会一起发送服务端SYN(SYN_RCVD)+ ACK 给客户端
最简就是三次握手建立tcp会话,多了几次就造成了资源浪费,所以不用超过三次