三次握手
SYN (同步序列编号):是 TCP/IP 建立连接时使用的握手信号。TCP 连接的第一个包,非常小的一种数据包。在客户机和服务器之间建立正常的 TCP 网络连接时,客户机首先发出一个 SYN 消息,服务器使用 SYN + ACK 应答表示接收到了这个消息,最后客户机再以 ACK 消息响应。这样在客户机和服务器之间才能建立起可靠的 TCP 连接,数据才可以在客户机和服务器之间传递。
Seq (序号):是 TCP 可靠传输的关键部分。序号是该报文段发送的数据组的第一个字节的序号。在 TCP 传送的流中,每一个字节都有一个序号。比如一个报文段的序号为 300,报文段数据部分共有 100 字节,则下一个报文段的序号为 400 。所以序号确保了 TCP 传输的有序性。
ACK (确认值):仅当 ACK = 1 时,确认号字段才有效。TCP 规定,在连接建立后所有报文的传输都必须把 ACK 置 1 。
Ack (确认号):指明下一个期待收到的字节序号,表明该序号之前的所有数据已经正确无误的收到。确认号只有当 ACK 标志为 1 时才有效。比如建立连接时,SYN 报文的 ACK 标志位为 0 。
状态
- CLOSED:表示初始状态
- SYN_SENT:表示客户端已发送 SYN 报文
- SYN_RCVD:表示服务器接受到了 SYN 报文
- ESTABLISHED:表示连接已经建立
过程
第一次握手:建立连接时,客户端发送 SYN 到服务器,并进入 SYN_SENT 状态
第二次握手:服务器收到请求后,回送 SYN + ACK 到客户端,此时服务器进入 SYN_RECV 状态;
第三次握手:客户端收到 SYN + ACK 包,向服务器发送确认 ACK 包,客户端进入 ESTABLISHED 状态,服务器收到请求后也进入 ESTABLISHED 状态,完成三次握手,此时 TCP 连接成功,客户端与服务器开始传送数据
过程
第一次握手 (客户端向服务器发送):Client 首先发送一个连接试探,ACK = 0 表示确认号无效,SYN = 1 表示这是一个连接请求或连接接受报文,同时表示这个数据报不能携带数据,seq = x 表示 Client 自己的初始序号( seq = 0 就代表这是第 0 号帧),这时候 Client 进入 SYN_SENT 状态,表示客户端等待服务器的回复
第二次握手 (服务器回复客户端):Server 监听到连接请求报文后,如同意建立连接,则向 Client 发送确认。
TCP 报文首部中的 SYN 和 ACK 都置为 1 ,ack = x + 1表示期望收到对方下一个报文段的第一个数据字节序号是 x + 1 ,同时表明 x 为止的所有数据都已正确收到( ack = 1 其实是 ack = 0 + 1 ,也就是期望客户端的第 1 个帧),seq = y 表示 Server 自己的初始序号( seq = 0 就代表这是服务器这边发出的第 0 号帧)。这时服务器进入 SYN_RCVD 状态,表示服务器已经收到 Client 的连接请求,等待 Client 的确认
第三次握手 (客户端向服务器发送):Client 收到确认后还需再次发送确认,同时携带要发送给 Server 的数据。ACK 置 1 表示确认号 ack = y + 1 有效(代表期望收到服务器的第 1 个帧),Client 自己的序号 seq = x + 1(表示这就是我的第1个帧,相对于第0个帧来说的),一旦收到 Client 的确认之后,这个 TCP 连接就进入 ESTABLISHED 状态,就可以发起 http 请求了
为什么是三次握手
- 在第一次通信过程中,A向B发送信息之后,B收到信息后可以确认自己的收信能力和A的发信能力没有问题。
- 在第二次通信中,B向A发送信息之后,A可以确认自己的发信能力和B的收信能力没有问题,但是B不知道自己的发信能力到底如何,所以就需要第三次通信。
- 在第三次通信中,A向B发送信息之后,B就可以确认自己的发信能力没有问题。
A-->B-->A-->B这样传三次能保证A有发有收,B也有发有收。多一次浪费少一次不够。
为什么是三次握手
最主要是防止已过期的连接再次传到被连接的主机
那为什么非要三次呢?怎么觉得两次就可以完成了。那 TCP 为什么非要进行三次连接呢?在谢希仁的《计算机网络》中是这样说的:
为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误。
在书中同时举了一个例子,如下:
"已失效的连接请求报文段”的产生在这样一种情况下:
Client 发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达 Server 。本来这是一个早已失效的报文段。但 Server 收到此失效的连接请求报文段后,就误认为是 Client 再次发出的一个新的连接请求。于是就向 Client 发出确认报文段,同意建立连接。假设不采用“三次握手”,那么只要 Server 发出确认,新的连接就建立了。由于现在 Client 并没有发出建立连接的请求,因此不会理睬 Server 的确认,也不会向 Server 发送数据。但 Server 却以为新的运输连接已经建立,并一直等待 Client 发来数据。这样,Server 的很多资源就白白浪费掉了。采用“三次握手”的办法可以防止上述现象发生。例如刚才那种情况,Client 不会向 Server 的确认发出确认。 Server 由于收不到确认,就知道 Client 并没有要求建立连接。"这就很明白了,防止了服务器端的一直等待而浪费资源。
为什么是三次握手
三次握手:
“喂,你听得到吗?”
“我听得到呀,你听得到我吗?”
“我能听到你,今天balabala……”
两次握手:
“喂,你听得到吗……吗……吗?”
“我听得到”
…………
“…………”
…………(等了一会未收到信息)
“……你妹的”
四次握手:
“喂,你听得到吗?”
“我听得到呀,你听得到我吗?”
“我能听到你,你能听到我吗?”
“……不想跟傻逼说话”