网络是怎么连接的

211 阅读10分钟

网络是如何连接的 前言: 从浏览器输入一个网址到浏览器返回响应这中间发生了什么?即假设把整个网络当做一个黑盒,输入是url,输出的是response,那么在这个黑盒里面发生了什么?一串url是怎么请求到网络上的资源的?我们都知道tcp/ip协议,但是他们在整个网络传输过程中,具体承担什么角色?他们的原理是什么?对于tezign而言,为什么切换不同的host就能访问到不同的环境,都知道是dns,虽然访问的是相同的域名,但是在不同的host下被解析成不同的ip,进而访问到不同的机器上。但是ip是怎么找到机器的?应用程序发送的数据是怎么被传输到服务器上的等等,这中间的过程其实都是非常复杂的。

示例: 以Tezign的一个url为例(vms-service.tezign.com/material/da…) 当在浏览器或者终端等地方输入这个url,整个请求流程应该如下所示

  1. Http请求生成 注意到最前面是https,所以是使用加密的http协议访问Web服务器 vms-service.tezign.com 则是被请求的域名 material/dam/public/query-common-dic 则是请求的资源 在这里指的是materila的有结果接口, 当点击Enter时候, 浏览器会根据当前系统版本及设置生成如下的一段Http request, GET /material/dam/public/query-common-dic HTTP/1.1 Host: vms-service.tezign.com Connection: keep-alive Pragma: no-cache Cache-Control: no-cache sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90" x-lang: zh-CN X-Token: d93fac5521b6d2338ca61dec3aa10690 sec-ch-ua-mobile: ?0 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36 X-User-Id: 100829 Content-Type: application/json;charset=UTF-8 Accept: / Origin: vms-t6.tezign.com Sec-Fetch-Site: same-site Sec-Fetch-Mode: cors Sec-Fetch-Dest: empty Referer: vms-t6.tezign.com/ Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9

  2. 获取域名对应的ip 如果直接输入的ip则可以跳过这步。服务器是不知道域名的,域名说白了就是全网共同维护的DNS。 通过DNS查询ip的操作称做域名解析,流程为:

  3. 生成发送给DNS服务器的查询信息 每台计算机上都自带了一个DNS客户端,由客户端生成查询信息(如果浏览器访问速度较慢的话,可以尝试加上114这个dns) 114.114.114.114 为国内通过的DNS解析服务器,访问国内网址好一点 8.8.8.8 为google提供的全球通过DNS解析,访问国外网址好一点

  4. 发送查询信息 会首先发送到最近的一台DNS服务器,如果最近一台没有相应的域名信息,则根据域名分层进行查找,如vms-service.tezign.com ,这个域名后面其实是隐藏了/. 所以会先发到跟DNS服务器,在跟服务里面找到com的地址,然后com的服务器里面保存了tezign的信息,将请求进一步转发到tezign,tezign里面找到vms-service,然后再进行返回(这里面澄清一下所谓的全球的只有13台根服务器,🇺🇸占了9台,美国可以随时断中国的网络,纯属扯断,并且13台也只是一个泛化的概念,真实的机器可能几百几千台镜像服务器分布世界各地,中国也是负责F、I、K、L根镜像服务器的管理 )

  5. dns查找记录

Class: 网络类型 互联网为IN 记录类型: A表示的是IP地址 域名 Class 记录类型 响应数据 vms-service.tezign.com IN A 10.80.82.192(env4)

  1. 接受DNS服务器返回的响应信息
  2. 取ip并保存到内存
  3. 委托协议栈进行信息发送 首先我们要明确 应用程序并不具备发送任何信息到网络上的能力,包括协议栈也不具备。真正能发的是网卡,但是网卡只认识 0跟1,所以应用程序想要发送的信息,需要经过协议栈进行包装。 网络中传输的最小单位是包:

对于TCP/IP 我们可以这样理解: 发快递时候 TCP是快递单 IP是快递盒。 快递单上描述了双方的各种信息,而快递盒决定了里面发送的物品不能超过快递盒的容量

  1. 创建套接字(创建套接字阶段) 套接字(Socket)是一个虚拟概念,他的实体其实是各种通信控制信息(简单的理解就是ip:port),通过两个套接字可以实现端与端的通信(一台机器上可能同时存在多个socket,但是一个端口同时只能存在一个socket,这也是为什么有时候tomcat异常退出后 再次启动报端口被占用的原因,socket未关闭 端口未被释放 无法进行下次通信)

  2. 将管道连接到服务器端的套接字上(连接阶段) 要想实现双方通信必须通信双方交换各自的同学控制信息(典型的信息ip、port),就像发邮件或者快递一样,必填发送人地址 接收方地址,这样接收方就能根据发送人地址进行回信。

连接的实际操作如下:

  1. 收发数据(通信阶段)
    1. 因为在TCP/IP网络中都是以包的形式进行传输,所以首先要进行包的切割,发送包的时机跟不同的版本有关系,大致为两种判断(a. 是否达到一个包能发送的最大长度 b.等待的时间),在尽量使用较少包的情况下保持较低延迟进行双方通信。

根据发送数据量的长度,还有每个包能发送的最大数据量(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状态 已经可以开始通信了,但是因为存在数据丢失(丢包),所以存在重试机制,如果第一次请求失败,会在一段时间后重试第二次,如果恰好第一次失败是网络问题或者其他临时阻塞问题,那么就会产生同时两个请求并且 第二次重试的正确请求可能会被遗弃,数据返回到被客户端放弃的第一次失败请求上。 4. 断开管道并删除套接字(断开阶段) 删除阶段 可能客户端主动断开,也可能服务端主动断开。

四次挥手:

以客户端主动发起断开连接为例 1、第一次挥手:客户端发送FIN =1 给服务端,表示我没数据发了,你还有没有数据发?没数据就👋🏻了 2、第二次挥手:服务器发送ACK = 1 表示我收到你的消息了,但是要不要关闭 我还要看一下数据还要不要发,先给你回个信,你先等一会 3、第三次挥手:服务端发送FIN = 1 表示我没数据了,你关吧 4、第四次挥手:客户端发送 ACK = 1 表示我关好了 你也关吧。 可能有人觉得第二次挥手是不是没有必要 可以将第二次跟第三次挥手结合到一个包发送这样效率不是更高吗,其实这里面也有一个问题存在就是,服务端接收到客户端发送的关闭请求后 并不会立即关闭,但是也不能客户端傻等着,必须要立即返回一个应答ack 表示信息收到,否则的话 客户端可能会重发该信息。 整体流程如下:

  1. 通过网络进行信息传递 上面的传输 仅仅只是指的将数据通过协议栈组装成包,通过网卡转换为光或者电信号进行发送,而从网卡到服务器这段,则是需要整个互联网的协助。比如我们在weWork发送的一条信息, 它的旅程应该是在被组装成包之后,首先会通过ip找到最近的路由器,也就是weWork的路由器,weWork的路由器再会根据包里面目标地址的ip查找到下一个路由地址 并覆盖掉包里面之前的MAC地址(也可以称为改写),就这样通过以太网依次传递直到发送到最终目的地。

  2. 服务器接受到请求并返回响应 操作跟客户端相反,由网卡接收到光或者电信号,并将其转换为数字信号0跟1。转换完成后会检查包的格式,有没有被分片,及是否自己为接收方等等信息。 如果都符合的话,数据会被交到tcp模块进行处理,根据ip port等信息确定该数据是传输给哪个套接字的,找到后将数据read到应用程序。