网络是如何连接的
网络是如何连接的
从浏览器输入一个网址到浏览器返回响应这中间发生了什么?即假设把整个网络当做一个黑盒,输入是url,输出的是response,那么在这个黑盒里面发生了什么?一串url是怎么请求到网络上的资源的?我们都知道tcp/ip协议,但是他们在整个网络传输过程中,具体承担什么角色?他们的原理是什么?对于tezign而言,为什么切换不同的host就能访问到不同的环境,都知道是dns,虽然访问的是相同的域名,但是在不同的host下被解析成不同的ip,进而访问到不同的机器上。但是ip是怎么找到机器的?应用程序发送的数据是怎么被传输到服务器上的等等,这中间的过程其实都是非常复杂的。
以Tezign的一个url为例( https://vms-service.tezign.com/material/dam/public/query-common-dic )
当在浏览器或者终端等地方输入这个url,整个请求流程应该如下所示
注意到最前面是https,所以是使用加密的http协议访问Web服务器 vms-service.tezign.com 则是被请求的域名 material/dam/public/query-common-dic 则是请求的资源 在这里指的是materila的有结果接口, 当点击Enter时候, 浏览器会根据当前系统版本及设置生成如下的一段Http request,
如果直接输入的ip则可以跳过这步。服务器是不知道域名的,域名说白了就是全网共同维护的DNS。
通过DNS查询ip的操作称做域名解析,流程为:
每台计算机上都自带了一个DNS客户端,由客户端生成查询信息(如果浏览器访问速度较慢的话,可以尝试加上114这个dns)
114.114.114.114 为国内通过的DNS解析服务器,访问国内网址好一点
8.8.8.8 为google提供的全球通过DNS解析,访问国外网址好一点
会首先发送到最近的一台DNS服务器,如果最近一台没有相应的域名信息,则根据域名分层进行查找,如vms-service.tezign.com ,这个域名后面其实是隐藏了/. 所以会先发到跟DNS服务器,在跟服务里面找到com的地址,然后com的服务器里面保存了tezign的信息,将请求进一步转发到tezign,tezign里面找到vms-service,然后再进行返回(这里面澄清一下所谓的全球的只有13台根服务器,🇺🇸占了9台,美国可以随时断中国的网络,纯属扯断,并且13台也只是一个泛化的概念,真实的机器可能几百几千台镜像服务器分布世界各地,中国也是负责F、I、K、L根镜像服务器的管理 )
Class: 网络类型 互联网为IN
记录类型: A表示的是IP地址
<colgroup><col width="200"><col width="100"><col width="100"><col width="149"></colgroup>
|
域名
|
Class
|
记录类型
|
响应数据
|
|
vms-service.tezign.com
|
IN
|
A
|
10.80.82.192(env4)
|
首先我们要明确 应用程序并不具备发送任何信息到网络上的能力,包括协议栈也不具备。真正能发的是网卡,但是网卡只认识 0跟1,所以应用程序想要发送的信息,需要经过协议栈进行包装。
网络中传输的最小单位是包:
对于TCP/IP 我们可以这样理解: 发快递时候 TCP是快递单 IP是快递盒。
快递单上描述了双方的各种信息,而快递盒决定了里面发送的物品不能超过快递盒的容量
套接字(Socket)是一个虚拟概念,他的实体其实是各种通信控制信息(简单的理解就是ip:port),通过两个套接字可以实现端与端的通信(一台机器上可能同时存在多个socket,但是一个端口同时只能存在一个socket,这也是为什么有时候tomcat异常退出后 再次启动报端口被占用的原因,socket未关闭 端口未被释放 无法进行下次通信)
要想实现双方通信必须通信双方交换各自的同学控制信息(典型的信息ip、port),就像发邮件或者快递一样,必填发送人地址 接收方地址,这样接收方就能根据发送人地址进行回信。
连接的实际操作如下:
根据发送数据量的长度,还有每个包能发送的最大数据量(MSS),就可以算出这次请求发送了多个包,每个包发送的位数是多少到多少。(抓包工具 wireshark )
可以看到鼠标选中这行seq为20269 len为135,所以第二行seq我20269+135=20404 ack全部为11代表全部为发送或者接收(也可以注意到前面的source与dst 分别代表着发送与接收的ip)
可以看到source与dst分别与上面相反,代表着上面的响应或者发送,可以看到ACK为20404 seq为11正好跟上面完全相反。
他们之间的规律是seq 代表着发送方发送的数据起始位数(第一次发送的起始位并不是0或者1而是一个随机数),ack代表着接收方接收到的位数+1(如ack为1000则代表接收了999的数据下一次希望接收到1000开头的数据)
在这里可能很多人想到了三次握手四次挥手,但是不必纠结为什么是三次,两次不行吗。他们的最终目的都是为了数据的安全有效传输。
三次握手:
目的: 连接到服务器的指定端口,并建立TCP连接,同步双方的序列号和确认号并交换TCP窗口信息
1、第一次握手 客户端发送一个没有数据的包(tcp头 syn = 1 seq = x)给服务端, 代表客户端进入syn-send(同步已发送)状态
2、第二次握手 服务端接收报文后,如果同意建立连接会返回一个syn = 1 seq = y = x+1 ack = x +1的数据包,代表服务端也进入syn-send(同步已收到)
3、第三次握手 客户端接收到服务端的响应后 再次给服务端发送 seq = x + 1 ack = y+1 代表客户端收到服务端的确认信息,并再次发送给服务端表示 我确认了你的确认 这时双方都进入 ESTABLISHED状态,双方可以传输数据了
为什么客户端要发送两次请求给服务端?
第二次返回给服务端的确认信息之前,其实双方已经都是处于syn-send状态 已经可以开始通信了,但是因为存在数据丢失(丢包),所以存在重试机制,如果第一次请求失败,会在一段时间后重试第二次,如果恰好第一次失败是网络问题或者其他临时阻塞问题,那么就会产生同时两个请求并且 第二次重试的正确请求可能会被遗弃,数据返回到被客户端放弃的第一次失败请求上。
删除阶段 可能客户端主动断开,也可能服务端主动断开。
四次挥手:
以客户端主动发起断开连接为例
1、第一次挥手:客户端发送FIN =1 给服务端,表示我没数据发了,你还有没有数据发?没数据就👋🏻了
2、第二次挥手:服务器发送ACK = 1 表示我收到你的消息了,但是要不要关闭 我还要看一下数据还要不要发,先给你回个信,你先等一会
3、第三次挥手:服务端发送FIN = 1 表示我没数据了,你关吧
4、第四次挥手:客户端发送 ACK = 1 表示我关好了 你也关吧。
可能有人觉得第二次挥手是不是没有必要 可以将第二次跟第三次挥手结合到一个包发送这样效率不是更高吗,其实这里面也有一个问题存在就是,服务端接收到客户端发送的关闭请求后 并不会立即关闭,但是也不能客户端傻等着,必须要立即返回一个应答ack 表示信息收到,否则的话 客户端可能会重发该信息。
整体流程如下:
上面的传输 仅仅只是指的将数据通过协议栈组装成包,通过网卡转换为光或者电信号进行发送,而从网卡到服务器这段,则是需要整个互联网的协助。比如我们在weWork发送的一条信息, 它的旅程应该是在被组装成包之后,首先会通过ip找到最近的路由器,也就是weWork的路由器,weWork的路由器再会根据包里面目标地址的ip查找到下一个路由地址 并覆盖掉包里面之前的MAC地址(也可以称为改写),就这样通过以太网依次传递直到发送到最终目的地。
操作跟客户端相反,由网卡接收到光或者电信号,并将其转换为数字信号0跟1。转换完成后会检查包的格式,有没有被分片,及是否自己为接收方等等信息。
如果都符合的话,数据会被交到tcp模块进行处理,根据ip port等信息确定该数据是传输给哪个套接字的,找到后将数据read到应用程序。
2020-04-29 广告