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