从输入url到页面返回到底发生了什么
1. 前言
Google应该是开发者平日里用得最多的网站之一,今早笔者在浏览器地址栏里键入www.google.com的时候,突然想了解下这背后的网络通信过程究竟是怎么样的。毕竟自己也算是一名Web开发工程师,光是TCP/IP的书也看过不少,但是至始自终却从未思考过这个问题,所以话不多说,让我们来一次深入体验吧。由于Google比较特殊,我们就用news.cnblogs.com站点做一个介绍好了。
本文适合具有一定的计算机网络相关背景知识的读者,不过只要最低不要比笔者还低就行。笔者在这方面大概战五渣的水平。
2. 网络通信过程
1. 域名解析
互联网上穿梭的数据包基本都是IP包,所以笔者与博客园新闻站点服务器传输的也是IP包,那么我们就需要博客园新闻站点服务器的IP地址。对于浏览器的使用者来说,我们只需要告诉浏览器我们需要的地址(在地址栏键入域名),那么之后解析IP地址的任务就会由浏览器代劳了。
IP包的格式为IP+TCP+HTTP。
浏览器程序通知DNS进程,请帮忙解析news.cnblogs.com的地址,此时解析IP地址的任务就由浏览器交给了DNS进程。
- DNS进程先检查自己的程序缓存,查看是否有news.cnblogs.com对应的IP地址,如果有,则直接返回给浏览器;否则,进入第2步。
- 检查本地的host文件,如果有对应的IP地址,依然选择直接返回给浏览器;否则,进入第3步。
- 检查本地的DNS服务器设置并发给消息给它,由它帮忙查找,这时解析IP地址的任务就由DNS进程交给了远程的DNS服务器。
- DNS进程发送查询报文 "query news.cnblogs.com" 至DNS服务器,DNS服务器首先检查自身缓存,如果存在记录则直接返回结果。
- 如果记录老化或不存在,则DNS服务器向根域名服务器发送查询报文"query news.cnblogs.com",根域名服务器返回.com域的权威域名服务器地址,这一级首先会返回的是顶级域名的权威域名服务器。
- DNS服务器向.com域的权威域名服务器发送查询报文"query news.cnblogs.com",得到.cnblogs.com域的权威域名服务器地址。
- DNS服务器向.cnblogs.com域的权威域名服务器发送查询报文"query news.cnblogs.com",得到主机news的记录,存入自身缓存并返回给DNS进程。
- DNS进程将查询返回的IP地址 114.55.49.182 存入自身缓存并返回给浏览器。
2. HTTP打包
浏览器将我们访问news.cnblogs.com的请求打包成HTTP格式,然后将打包好的HTTP包和IP地址告诉TCP进程。
TCP进程和IP进程在本文中是一个抽象概念,专指操作系统内核对TCP/IP协议族的实现。
HTTP 是一个客户端和服务器端请求和响应的标准TCP。
3. 三次握手
TCP进程作风稳健,所以并不会轻易地将HTTP包和IP地址发给IP进程,所以这就引出了TCP通信三次握手。三次握手中,TCP进程决定先不发HTTP包,而是先要确保自己的IP包能够被远程服务器正常接收,同时,远程服务器的IP包也能被己方机器正常接收。
TCP进程:洞腰洞腰,我是洞拐,听到请回话 Cnblogs服务器:洞拐洞拐,我是洞腰,我听到了 TCP进程:OK,我听到你说话了。
4. HTTP数据传输
所谓兵马未动,粮草先行,还没真正进行数据交流呢,双方就已经传递了三个IP包了。不过这样一来,双方都能听到对方的回复了。现在TCP进程可以委托IP进程安心大胆地发送包含HTTP数据的IP包了。
这里还有一个问题,由于发送的IP包都是通过分组交换发出的,所以TCP进程怎么知道哪个IP包被服务端正确地接收了呢。这里就引出了SEQ和ACK的概念。
SEQ=Sequence Number ACK=Acknowledge Number
这两个字段分别被包裹在TCP头部(别忘了我们的IP包组成结构)。比如我们每次要传输1000字节的数据,初始序列号为1,那么就将SEQ设置为1,然后本地的TCP进程就把这1000个字节打包,然后层层地封装、传输,并最终到达服务器TCP进程。
讲完了SEQ的作用,ACK的作用呢?顾名思义,它是用来“确认收货”的。比如说假如我们发起了一个POST请求,第一次传输的报文中含有1000个字节的信息,服务端在接收到之后那么就将ACK标为1001,表示确认收到并返回给客户端(没有任何数据,只是一个IP+TCP而已),这样客户端可以安心传输第二波从1001序列号开始的数据了。当然啦,我们只是访问news.cnblogs.com站点界面,只是普通的HTTP GET请求而已。
接下来,我们静待news.cnblogs.com站点界面的返回即可。在这个过程中,存在一去一回表示数据和确认的两个IP包。
5. 服务器传回网页
cnblogs新闻站点服务器将首页封装成HTTP格式,通过TCP进程按照类似第4步的流程返回给我们的机器。这一个过程,数据传输也是基于分组交换的方式。所以又是两个IP包(只考虑一次传输)。
6. 释放TCP连接
经过两边不断的“交易”,网页数据终于基本传输完毕了,我们的浏览器也根据报文内容渲染出了最终的界面。但是这就结束了吗?显然还没有,我们还需要释放TCP连接以回收资源。
计算机上建立了大量TCP连接却没有释放可是要出大问题的,《使用HttpClient的优解》
不同于通信连接阶段的三次握手,释放TCP连接则是四次握手。类比通信的一端有一个数据传输口和一个数据接收口,分别是另一端的数据接收口和数据传输口,这两根管道需要依次被关闭。
TCP进程:洞腰洞腰,我是洞拐,数据传输完毕,我要关闭连接我的数据传输口了 Cnblogs服务器:洞拐洞拐,我是洞腰,我听到了,你关闭吧 (TCP进程默默关闭数据传输口(Cnblogs服务器的数据接收口)) Cnblogs服务器:洞拐洞拐,我是洞腰,数据传输完毕,我要关闭连接我的数据传输口了 TCP进程:洞腰洞腰,我是洞拐,我听到了,你关闭吧 (Cnblogs服务器默默关闭数据传输口(TCP进程的数据接收口))
不考虑超时重传,这里又用了4个IP包。
让我们用一张图作为本次数据传输的总结。其中SYN(synchronous)是TCP/IP建立连接时使用的握手信号。
从图上也可以很直观的看出,本次通信总共用了3+2*2(双向通信)+4=11个IP包。
3. 参考资料
- 计算机是如何聊天的?
- 互联网协议入门
- 如何生动形象、切中要点地讲解 OSI 七层模型和两主机传输过程?
- ASP.NET Web API中的Controller
- iOS 转场动画探究(二)
- Swift 面向对象解析(二)
- 谈谈基于OAuth 2.0的第三方认证 [中篇]
- [ASP.NET Web API]如何Host定义在独立程序集中的Controller
- ASP.NET Web API自身对CORS的支持: EnableCorsAttribute特性背后的故事
- 【黑客解析】黑客是如何实现数据库勒索的 ?
- 直播回看:高可用架构入门 —— 腾讯云架构演变及经验
- 【腾讯云的1001种玩法】十分钟轻松搞定云架构之一 :从上云开始
- 【腾讯云的1001种玩法】十分钟轻松搞定云架构之二:更好的网络
- 【腾讯云的1001种玩法】十分钟轻松搞定云架构之三:更大的存储
- Socket学习总结系列(一) -- IM & Socket
- 【腾讯云的1001种玩法】十分钟轻松搞定云架构 之四:替你分心的负载均衡
- 【腾讯云的1001种玩法】十分钟搞定云架构 · 什么是Bucket、什么是Object
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Golang中的interface是干嘛的?从面向对象中的多态与接口开始说起……
- pandas | DataFrame基础运算以及空值填充
- C++设计模式笔记(08) - Factory Method工厂方法
- 【Code】GraphSAGE 源码解析
- Kafka常见的导致重复消费原因和解决方案
- 近30个MySQL常用函数,必须推荐!
- 搞定 CompletableFuture,并发异步编程和编写串行程序还有什么区别?你们要的多图长文
- 用注解实现 MyBatis 开发
- MyBatis 实现数据的增删改查
- 0790-5.16.2-NameNode服务的edits不同步异常
- 0789-不停止MySQL服务重做备库的方法
- 防盗链Apache和Nginx配置对比
- Python 类特殊方法__getitem__
- 前端自动化测试探索和实践
- 我的开发日记(十四)