对于教材中的描述:
- 一次握手:客户端发送带有 SYN(SEQ=x) 标志的数据包 -> 服务端,然后客户端进入 SYN_SEND 状态,等待服务器的确认;
- 二次握手:服务端发送带有 SYN+ACK(SEQ=y,ACK=x+1) 标志的数据包 –> 客户端,然后服务端进入 SYN_RECV 状态
- 三次握手:客户端发送带有 ACK(ACK=y+1) 标志的数据包 –> 服务端,然后客户端和服务器端都进入ESTABLISHED 状态,完成 TCP 三次握手。
我的疑问包括:
- 为什么SEQ在括号里,而且第一次握手时在SYN的括号里,第二次握手时在ACK的括号里
- 为什么ACK括号里边还要再写一个ACK
- 为什么第二次握手的ACK的括号里有SEQ和ACK,而第三次握手的ACK括号里只有一个ACK
所以我一直感觉很困惑,看的很迷糊,即使知道三次握手是个怎么回事,还是很迷惑。
想要看懂我的理解方式,需要一些前置知识:
要先知道:
TCP的段(也就是TCP的内容)由Header和Body两部分组成,而在握手过程中我们提到的几个变量(暂且这么称它们)都位于TCP段的Header部分
然后要明确:
SYN,SEQ,ACK都是TCP的头部,也就是Header中的字段,也就是说他们是平级的,个人认为教材中将SEQ写在括号中不太合适
其次:
在TCP头部中,其实有两个ACK,只不过他们缩写都是ACK,实际名字分别是Acknowledgment Flag
和Acknowledgment Number
也就是说,三次握手建立连接的过程中
一共有如下Header字段要被使用:
- SYN:取值为0或1,在三次握手过程中出现的两次,取值都是1。SYN为1时表示我想要建立一个连接。
- SEQ:取值为数字,表示序列号,告诉对方我的数据从这个值开始编号(或者说当前发送给你的这个段的序列号就是这个值)
- Acknowledgment Flag:取值为0或1,标志Acknowledgment Number字段是否可用
- Acknowledgment Number:取值为数字,表示序列号,告诉对方我期望你从这个序列号为这个值的段开始发送后边的数据(确认收到了序列号为Acknowledgment Number-1前边的所有数据)
然后再去理解:
- 一次握手:客户端发送带有 SYN(SEQ=x) 标志的数据包 -> 服务端,然后客户端进入 SYN_SEND 状态,等待服务器的确认;
- 二次握手:服务端发送带有 SYN+ACK(SEQ=y,ACK=x+1) 标志的数据包 –> 客户端,然后服务端进入 SYN_RECV 状态
- 三次握手:客户端发送带有 ACK(ACK=y+1) 标志的数据包 –> 服务端,然后客户端和服务器端都进入ESTABLISHED 状态,完成 TCP 三次握手。
其实可以改写为(我个人认为更清晰):
- 一次握手:客户端发送带有 SYN=1,SEQ=x 头部的数据包 -> 服务端,然后客户端进入 SYN_SEND 状态,等待服务器的确认;
- 二次握手:服务端发送带有 SYN=1,Acknowledgment Flag=1,SEQ=y,Acknowledgment Number=x+1头部的数据包 –> 客户端,然后服务端进入 SYN_RECV 状态
- 三次握手:客户端发送带有 Acknowledgment Flag=1,Acknowledgment Number=y+1头部的数据包 –> 服务端,然后客户端和服务器端都进入ESTABLISHED 状态,完成 TCP 三次握手。