重要性
在面试开发工程师这类岗位,笔试面试问到TCP三次握手的概率很大,所以我们要学好
概述
我们在做TCP编程时,使用socket套接字,socket套接字处于 运输层 的上层,如下图:
在建立TCP连接时,socket只需要调用connect()方法或函数(在不同的编程语言中会有差别),但是处于下层的TCP协议要传输3个数据包(称之为3次握手)
类比
这就相当于领导对下属说:“沏杯茶”,领导只说了一句话,但下属要做 烧水、沏茶、把茶端给领导 这3个步骤
在TCP/IP协议中,TCP协议提供可靠的连接服务,采用 三次握手 建立一个连接,然后才能 传输数据,进行通信,在结束时,要 四次挥手 断开连接
参见 TCP报头格式
三次握手
三次握手的过程,类似我们发微信电话,双方为了确定连通了,要互相问对方是否能收到,如下图:
双方确认都能听到后,才开始正式说话
建立一个TCP连接时,需要客户端和服务器按照特定的顺序发送 3个数据包,称之为 3次握手,确认连接已经建立
在socket编程中,这一过程由客户端执行connect来触发
原则上任何数据传输都无法确保绝对可靠,三次握手只是确保可靠的基本需要
第一次握手
客户端向服务器端发送数据包,报文首部中的SYN=1、ACK=0,随机产生一个序列号x
客户端进入SYN_SEND状态。
注意:
SYN=1的报文 不能携带数据,但要 消耗掉一个序号
通过命令
netstat -ano查看
第二次握手
服务器接收到数据包,由SYN=1、ACK=0可知,有客户端请求建立连接。
当同意建立连接时,发送确认数据包,SYN=1、ACK=1,随机产生一个序列号y(服务器端),确认号x+1
服务器端进入SYN_RCVD状态。
第三次握手
客户端接收到确认数据包后,由SYN=1、ACK=1可知服务器同意建立连接,向服务器发送确认数据包 ,SYN=0、ACK=1,序号x+1(),确认号y+1
客户端进入ESTABLISHED状态。
服务器端接收确认数据包,也进入ESTABLISHED状态,完成三次握手,可以开始 传输数据 了。
注意:
第三次握手时,客户端发送的数据包,SYN=0、ACK=1的报文 可以携带数据,如果不携带数据则不消耗序号,此时下一个报文的序号与当前报文的序号相同
总结
| 序号 | 方向 | 序号 | 确认号 | SYN | ACK |
|---|---|---|---|---|---|
| 1 | 客户端-服务器端 | 10000 | 0 | 1 | 0 |
| 2 | 服务器端-客户端 | 20000 | 10000+1=10001 | 1 | 1 |
| 3 | 客户端-服务器端 | 10001 | 20000+1=20001 | 0 | 1 |
为什么需要三次握手
由于网络是不稳定的,为了防止已经失效的连接请求报文段突然又传到服务端,因而产生错误
前两次握手都好理解,关键是第三次握手,这种情况是:
- 客户端发出去的第一个 连接请求 报文并没有丢失,而是在某个网络节点发生滞留
- 客户端没有收到服务器端确认报文,以为服务器没有收到,此时重新向服务器发送 连接请求 报文,此后客户端和服务器完成连接,传输数据,然后关闭连接。
- 之前滞留的那一次 连接请求 报文,网络通畅了到达了服务器,这个报文本该是失效的,假设是 两次握手的机制 ,将会让服务器建立连接,但客户端没有建立连接,因此不会理会服务端的确认包,也不会向服务端发送数据,这将导致不必要的错误和资源的浪费。
- 采用三次握手,客户端就不会向服务端发出确认,服务端由于收不到确认,就知道客户端没有要求建立连接,从而不建立该连接。
感谢
https://www.cnblogs.com/zmlctt/p/3690998.html
https://blog.csdn.net/sssnmnmjmf/article/details/68486261
https://blog.csdn.net/peipeiluo/article/details/79780164
https://blog.csdn.net/HappyRocking/article/details/78198776
https://www.jianshu.com/p/e7f45779008a




