TCP连接:三次握手
简单理解
简单的理解就是:
scss
复制代码
客户端:hello,你好,你是server吗?
服务端:hello,你好,我是server,你是client吗
客户端:yes,我是client
开始数据传输.....
——————————————————————————————————————————
客户端(男人):我喜欢你,咱俩处对象吧
服务端(女人):我也喜欢你,我答应你
客户端(男人):太棒了,我们现在去看电影吧
开始数据传输.....
然后双方就正确建立连接,开始传输数据
详细分析
-
第一次握手:客户端发送一个带
SYN=1,Seq=x的数据包到服务器端口第一次握手,由浏览器发起,告诉服务器我要发送请求了- SYN(synchronous):请求建立连接
- seq(sequence):随机序列号
- 请注意TCP规定SYN被设置为1的报文段不能携带数据但要消耗掉一个序号。
-
第二次握手:服务器发回一个带
SYN=1, ACK=1, seq=y, ack= x+1的响应包以示传达确认信息第二次握手,由服务器发起,告诉客户端我准备接受了,你赶紧发送吧- ACK(acknowledgement):确认,是一个确定字符
- ack:ack=上一次的seq+1,作用是接受上一次远端主机传来的seq,加一然后再传给客户端,提示客户端已经成功接收上一次所有数据
- 请注意这个报文段不能携带数据,因为它是SYN被设置为一的报文段但同样要消耗掉一个序号
-
第三次握手:客户端再回传一个带
ACK,seq = x + 1, ack = y + 1的数据包,代表“握手结束”第三次握手,由浏览器发送,告诉服务器,我马上就发了,准备接受吧- 确认报文段可以携带数据。但如果不携带数据则不消耗序号,在这种情况下所发送的下一个数据报文段的序号仍是x + 1
然后双方就正确建立连接,开始传输数据
SSL/TLS四次握手
HTTPS 建立连接的过程,先进行 TCP 三次握手,再进行 TLS 四次握手(仅对https)
因为 HTTPS 都是基于 TCP 传输协议实现的,得先建立完可靠的 TCP 连接才能做 TLS 握手的事情。
第一次握手:客户端发出请求Client Hello
-
首先,客户端先向服务器发出加密通信的请求,这被叫做clienthello请求。
-
在这一步,客户端主要向服务器提供以下信息:
- 支持的协议版本,比如TLS1.0版本
- 支持的加密方法,比如RSA公钥加密
- 一个客户端生成的随机数(client random) , 稍后用于生成对话密钥(session key)
第二次握手:服务器回应Server Hello
-
服务器收到客户端请求后,向客户端发出回应,这叫做serverhello
-
这一步服务器主要干三件事:
- 确认使用的加密通信协议版本,比如TLS1.00版本。如果游览器与服务器支持的版本不一致,服务器关闭加密通信
- 确认使用的加密方法(客户端所支持),比如RSA公钥加密
- 将服务器证书、非对称加密的公钥,以及一个随机数(Server random)发送给客户端游览器
客户端验证证书
客户端收到服务器回应以后,首先验证服务器证书,验证手段就是执行如下三种检查:
- 检查证书是否已过期;
- 检查证书中的域名与实际域名是否一致
- 检查证书是否是可信机构颁布的
如果,上述过程中有任何一个环节发现问题,那么浏览器就会向访问者显示一个警告,由其选择是否还要继续通信。如果证书受信任,或者是用户接受了不受信的证书,浏览器会生成一串新的随机数(Premaster secret ) 。
第三次握手:客户端回应
此时,浏览器会根据前三次握手中的三个随机数:
- Client random
- Server random
- Premaster secret
通过一定的算法来生成 “会话密钥” (Session Key) ,这个会话密钥就是接下来双方进行对称加密解密使用的密钥!
第四次握手:服务端回应
服务端收到客户端的回复,利用已知的加密解密方式进行解密,服务器收到客户端的第三个随机数( Premaster secret) 之后,使用同样的算法计算出 “会话密钥” (Session Key)。
至此,整个握手阶段全部结束。接下来,客户端与服务器进入加密通信,就完全是使用普通的 HTTP 协议,只不过用 “会话密钥” 加密内容。(非对称加密解密将不再使用,接下来完全由对称加密接手了,因为密钥已经安全的传送给了通信的双方)
总结
-
客户端请求建立SSL链接,并向服务发送一个随机数–Client random和客户端支持的加密方法,比如RSA公钥加密,此时是明文传输
-
服务端回复一种客户端支持的加密方法、一个随机数–Server random、授信的服务器证书和非对称加密的公钥
-
客户端收到服务端的回复后利用服务端的公钥,加上新的随机数–Premaster secret 通过服务端下发的公钥及加密方法进行加密,发送给服务器
-
服务端收到客户端的回复,利用已知的加解密方式进行解密,同时利用Client random、Server random和Premaster secret通过一定的算法生成HTTP链接数据传输的对称加密key – session key
断开连接:TCP 四次挥手
在渲染完成后,浏览器可能会继续加载页面中的其他资源,如异步加载的内容或者通过JavaScript生成的动态内容。
而在此过程中,如果没有其他资源需要加载,浏览器将与服务器之间的TCP连接断开。
简单理解
复制代码
主动方:我已经关闭了向你那边的主动通道了,这是我最后一次给你发消息了,之后只能被动接收你的信息了
被动方:收到你通道关闭的信息
被动方:那我也告诉你,我这边向你的主动通道也关闭了
主动方:最后收到你关闭的信息,OK结束
断开连接,结束通讯
————————————————————————————————————————————————————————————————————————————
提出分手的可能是男生(客户端),也可能是女生(服务端)
主动方:分手吧,我不喜欢你了!
被动方:行,你等我忙完手上的工作我在收拾你!
被动方:我忙完了,分手就分手!
主动方:好,好聚好散,拜拜!
断开连接,结束通讯
详细分析
由于TCP连接是全双工的,因此,每个方向都必须要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的连接,收到一个FIN只是意味着这一方向上没有数据流动了,即不会再收到数据了,但是在这个TCP连接上仍然能够发送数据,直到这一方向也发送了FIN。首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭。
任何一方都可以在数据传送结束后发出连接释放的通知,所有主动发起关闭请求可以是客户端,也可以是服务端
这里我们假设是由客户端先主动发起关闭请求
-
第一次挥手:TCP客户进程会发送TCP连接释放报文段,并进入终止等待1(FIN-WAIT-1)状态。
- FIN:终止位,表示断开TCP连接
- TCP规定终止位FIN等于1的报文段即使不携带数据,也要消耗掉一个序号
-
第二次挥手:TCP服务器进程收到TCP连接释放报文段后,会发送一个普通的TCP确认报文段并进入关闭等待(CLOSE-WAIT)状态。
- 序号seq字段的值设置为v,与之前收到的TCP连接释放报文段中的确认号匹配
- TCP客户进程收到TCP确认报文段后就进入终止等待2(FIN-WAIT-2)状态,等待TCP服务器进程发出的TCP连接释放报文段
- 这时的TCP连接属于半关闭状态,也就是TCP客户进程已经没有数据要发送了。但如果TCP服务器进程还有数据要发送,TCP客户进程仍要接收,也就是说从TCP服务器进程到TCP客户进程这个方向的连接并未关闭,这个状态可能要持续一段时间。
-
第三次挥手:TCP服务器进程发送TCP连接释放报文段
- 假定序号seq字段的值为w,这是因为在半关闭状态下,TCP服务器进程可能又发送了一些数据。
- 确认号ack字段的值为u+1,这是对之前收到的TCP连接释放报文段的重复确认。
-
第四次挥手:TCP服务器进程收到确定报文段后就进入关闭状态,而TCP客户进程还要经过2MSL后才能进入关闭状态。
之后断开连接,结束通讯
写在最后
作者:前端实习生鲸落
github地址:github.com/xiaojunnany…
个人博客:鲸落 (xiaojunnan.cn)