Android网络编程(三) 之 网络请求握手过程

1 一次网络请求的过程

我们平常在浏览器输入一个网址回车后经过了大概不到一秒时间的网络请求便可展示出相应的页面,其实这样一次完整的网络请求过程要经过好几个步骤:

第一步:DNS解析IP地址;

第二步:TCP三次握手建立连接;

第三步:如果是HTTPS的话,还要进行TLS握手验证签名证书;

第四步:客户端发起HTTP请求

第五步:服务器响应HTTP请求

第六步:客户端浏览器接收到内容进行解析html、css、js

第七步:浏览器对页面进行渲染

 

2 DNS解析IP过程

DNS( Domain Name System)叫作“域名系统”,是一种组织成域层次结构的计算机和网络服务命名系统,它用于TCP/IP网络,它所提供的服务是用来将主机名和域名转换为IP地址的工作。其过程大概是这样:

第一步:通过java.net.InetAddress类来调用相应的方法来查看自身缓存是否存在,因为Android系统中有对DNS做了二层的缓存处理。

第二步:如果java.net.InetAddress并没有缓存,则再通过查看虚拟机的DNS缓存来判断是否存在,这是第二层的缓存。

第三步:如果经过缓存后都不能解析到IP地址,则会再向本地Hosts文件来读取解析。

第四步:如果通过以上在本机上无法完成域名的解析,那么系统只能请求本地区的域名解析服务系统进行解析,比如校园网,如果连接的运营商网络,那么本地域名解析服务器就是本地区的运营商来提供服务。

第五步:如果本地域名解析服务器还没有完成解析的话,那么本地域名解析服务器将向根域名服务器发起解析请求。根域名服务器返回的是所查域的通用顶级域(Generic top-level domain,gTLD)地址,如:.com、.cn、.org、.edu等。

第六步:本地域名解析服务器向gTLD服务器发起请求。

第七步:gTLD服务器接收本地域名服务器发起的请求,并根据需要解析的域名,找到该域名对应的Name Server域名服务器 ,通常情况下,这个Name Server服务器就是你注册的域名服务器,那么你注册的域名的服务商的服务器将承担起域名解析的任务。

第八步:Name Server服务器查找域名对应的IP地址,将IP地址连同生存时间值(Time To Live,TTL)返回给本地域名服务器。

第九步:本地域名服务器缓存解析后的结果,缓存时间由TTL时间来控制。

第十步:返回解析结果给用户,用户系统将缓存该IP地址,缓存时间由TTL来控制。至此解析过程结束。

 

3 TCP三次握手

所谓的三次握手(Three-Way Handshake)即对每次发送的数据量是怎样跟踪进行协商使数据段的发送和接收同步,根据所接收到的数据量而确定的数据确认数及数据发送、接收完毕后何时撤消联系,并建立虚连接。

第一次握手:客户端发送连接请求报文段,将SYN(Synchronize Sequence Numbers,同步序列号)设置为1,并设置一个seq=x ,(Sequence Number,序列号)(x 是由操作系统根据一定的规则生成的,可以认为是一个随机数)将这个报文(SYN=1 seq=x)发送到服务器。此时,客户端进入同步已发送状态SYN_SEND,等待服务端的确。

第二次握手:服务器收到客户端的请求报文段SYN后,若同意建立连接,需要对这个SYN报文段进行ACK(Acknowledgment Numbe,确认字符)确认,设置ack=x+1,同时,自己还要发送SYN请求信息,将SYN设置为1,seq=y。服务器端将上述所有信息放到一个报文段(ACK=1 ack=x+1,SYN=1 seq=y)中一并发送给客户端,此时服务器进入同步已接收状态SYN_RECV

第三次握手:客户端收到服务器的SYN+ACK报文段,要对服务器发送确认的确认,即进行ACK的确认,将ack设置为y+1,向服务器发送ACK报文段(ACK=1 ack=y+1),这时客户端和服务器端都进入已连接状态状态ESTABLISHED,完成三次握手。

例个粟子:

第一次握手:客户端说:喂,你好,你能听到吗?

第二次握手:服务端说:你好,我能听到,你能听到我讲话吗?

第三次握手:客户端说:我也能听到你讲话

经过对话确认相互听到这后,他们就可以互相开始讲话了…

为什么要采用三次握手,而两次不行吗?

现假设在建立连接过程中出现一种异常情况:客户端发出的第一个连接请求报文段并没有丢失,而是在某些网络结点长时间滞留了,以致延误到连接释放以后的某个时间才到达服务端。本来这是一个早该失效的报文段,但是服务端收到了此失效的连接请求了,它并不知道这是一个失效的请求,就误以为是客户端又发出一次新的连接请求,于是就向客户端发出确认报文段,同间建立连接。我们假设不采用三次握手,那么这时连接关系就会被建立了。

由于现在客户端并没有发出建立连接的请求,因此是不会理睬服务端的确认的,也不会向服务端发送数据,但是服务端却以为已经建立了连接,并一直等待客户端发数据,这样服务端的就会造成资源浪费。

所以采用三次握手就可以有效防止上述现象的发生。当第三次握手时,客户端不会向服务端的确认发出确认,服务端由于收不到确认的确认,就会明白客户端其实并没有要求建立连接。

 

4 四次挥手

跟三次握手相对的是四次挥手(Four-Way Wavehand),就是指断开一个TCP连接时,挥手方可以是客户端也可以是服务端,他们之间总共发送4个包以确认连接的断开,其过程如下:

第一次挥手:主机A发送断开报文段,将FIN(Finish Number)设置为1,并设置一个seq=u(u是上一个最后传输的字节序号+1)将这个报文(FIN=1 seq=u发送后,主机A进入终止等待1状态FIN_WAIT_1

第二次挥手:主机B收到主机A发来的FIN报文段,需要对这个该报文段进行ACK确认,设置ack=u+1,并且带上序列号seq=v,主机B将上述所有信息放在一个报文段(ACK=1 ack=u+1 seq=v)中一并发回给主机A,此时主机B进入关闭等待状态CLOSE_WAIT。当主机A收到主机B的确认请求后,此时主机A就会进入终止等待2状态FIN_WAIT_2,等待主机B发送连接释放报文,此时主机B还可以对主机A进行正常数据发送。

第三次挥手:如果主机B将最后的数据都发送完毕后,已经没有要发送的数据,则会向主机A发送连接释放报文,将FIN设置为1,并选择seq=w和ACK确认,设置ack=u+1,将该释放报文(FIN=1 seq=w, ACK=1 ack=u+1)发出,此时主机B进入最后确认状态LAST_ACK

第四次挥手: 主机A收到释放报文后,就需要发出最后确认,将ack设置为w+1,并且带上序列号seq=u+1,向主机B发送报文段(ACK=1 ack=w+1 seq=u+1),此时主机A进入了时间等待状态TIME_WAIT,此时TCP连接并没立刻断开,而是经过2*MSL(最长报文段寿命,通常为2分钟,为了确保这段时间内不会重新创建相同地址和端口的新连接)的时间后才撤销传输控制块,进入关闭状态CLOSED。在这时间内,当主机B收到主机A发出的最后确认后,就会立即进入关闭状态CLOSED并撤销传输控制块至此,TCP的四次挥手就完成了。

例个粟子:

第一次挥手:A说:我说完了,我要闭嘴了,不想再说什么了。

第二次挥手:B说:我收到了知道你已经说完了,但是我还有话说。

经过了B也把话唠叨完后…

第三次挥手:B说:我也说完了,我也要闭嘴了,不说了。

第四次挥手:A说:我收到了知道你也已经说完了但是A不太放心,等待了一段时间后(2个最大报文生命周期),确实没有听到说话了,知道该离开了; B在收到A已经知道自己说完后就立即离开了。

为什么连接的时候是三次握手,关闭的时候却是四次挥手?

TCP是全双工模式,这就意味着,当主机A发出FIN报文段时,表示告诉主机B,我的数据已经全部发送完毕了,不再发送数据了。这时主机B返回ACK报文段时,表示他已经知道主机A没有数据发送了,但是并不代码主要B没有数据要发送啊,所以此时主机B还是可以发送数据到主机A的,当主机B也发送了FIN 报文段时,这个时候就表示主机B也没有数据要发送了,就会告诉主机A,我也没有数据要发送了。之后彼此 就会中断这次TCP连接。

 

5 TLS握手

SSL/TLS协议的基本思路

第一步:客户端向服务器端索要公钥;

第二步:服务端返回包含公钥的可信任的证书;

第三步:客户端验证证书确定公钥,利用公钥使用非对称加密的方式进行私密协商如何生成对话密钥(非对称加密效率低,但安全性高,所以说服务器公钥只用于加密"对话密钥"本身)

第四步:服务端收到协商后解密结果,往后双方通信就使用对称加密方式生成对话密钥(对称加密效率高,减少通信耗时)

四次握手的详细过程

第一次握手:客户端向服务器发出加密通信的请求(ClientHello),提供以下信息:

         支持最高的协议版本version,如:TLS1.2

         支持的加密套件cipher suites列表:身份验证算法、密钥交换算法、对称加密算法和信息摘要

         支持的压缩算法compression methods 列表,用于后续的信息压缩传输

随机数random_C,用于后面生成对话密钥

扩展字段 extensions,支持协议与算法的相关参数以及其它辅助信息等

第二次握手:服务端收到客户端请求后便回应请求(server_hello + server_certificate + sever_hello_done)(如果服务端也要求客户端提供证书,像网银中的U盾类的,则会在此再包含一项请求):

         server_hello:服务端返回协商的信息结果,包括以下信息:

                   协议版本version

                   确认使用加密套件cipher suite

                   选择的压缩算法 compression method

                   随机数 random_S,用于后面生成对话密钥

                   扩展字段 extensions,支持协议与算法的相关参数以及其它辅助信息等

         server_certificates:含公钥的服务器端配置的证书

         server_hello_done:通知客户端信息发送结束

第三次握手:客户端收到服务器回应以后,会对返回的证书进行验证。如果证书不是可信机构颁布、或者证书中的域名与实际域名不一致、或者证书已经被吊销、或者证书已经过期,就会向访问者显示一个警告,由其选择是否还要继续通信。如果证书没有问题,客户端继续向服务器发送信息(client_key_exchange  +  change_cipher_spec  +  encrypted_handshake_message(Finished))(如果服务端要求客户端也提从证书,像网银中的U盾类的,则在此发送证书及其相关信息):

         client_key_exchange:计算产生随机数字pre_master,并利用证书提取的公钥使用非对称加密的方式进行加密传递

(客户端此时已经掌握计算对话密钥的方法:enc_key=Fuc(random_C, random_S, pre_master))

         change_cipher_spec:表示后续的通信都将采用双方协商的密钥和加密算法进行加密通信

         encrypted_handshake_message:通知结束握手,结合前面发送通信所有内容的hash值与其它相关信息生成一段数据,用于供服务端进行校验

第四次握手:服务端收到客户端传递的加密过的pre_master后用私钥进行解密,也通过enc_key=Fuc(random_C, random_S, pre_master)计算出对话密钥,然后给客户端回复信息(change_cipher_spec  +  encrypted_handshake_message(Finished)):

         change_cipher_spec:表示后续的通信都将采用双方协商的密钥和加密算法进行加密通信

         encrypted_handshake_message:通知结束握手,结合前面发送通信所有内容的hash值与其它相关信息生成一段数据,用于客户端进行校验

 

至此,整个TLS握手阶段全部结束。接下来,客户端与服务器进入的通信,就是普通的HTTP协议,只不过用上了对话密钥加密了内容。

 

你可能感兴趣的:(Android进阶与总结,Android网络编程,三次握手,四次挥手,TLS握手,DNS解析)