关于HTTP

前言

之前在知乎看到有人问的一个问题:前端工程师难道不该熟悉HTTP,掌握ECMAScript标准吗?回答中有很多资深人士把我深深的打击了。。那时我对这两个东西的理解仅仅停留在。。。哦。有这个东西啊的水平。。
所以今天就总结一下之前看的一些HTTP相关的知识吧!

HTTP

超文本传输协议。。Hyper text tranfer protocal?HTTP跟我们的HTML很像。HTML是超文本标记语言,那么我们的HTTP就是为了传输所谓的超文本。标记语言可以将收集起来的文档组合成为一个完整的信息库!并且可以将文档库与世界上其他文档集合链接起来!这样一来,读者可以完全控制文档在屏幕上的显示,还可以通过超链接来控制浏览信息的顺序。这就是超文本!
超文本的传输需要遵守的就是HTTP协议了!而在这之上还有一个概念,就是WWW。
WWW是万维网的简称,当你想要进入万维网上的一个网页,或者其他的网络资源时,你就会采用WWW的服务模式,即web客户端(常用浏览器)访问web服务器上的页面。
简单的来说,万维网只是互联网的意向服务,这项服务代表我们的网页。
互联网的数据传输语言分两部分,TCP(Transmission Control Protocol)和IP(internet protocol)。互联网数据传输要遵守TCP/IP协议,而HTTP协议只是TCP/IP协议中的一个部分。
万维网系统中,存在一个统一资源标识符:URL。
我们的URL。分为协议+域名+地址+hash+附带字段。
当我们输入了URL并敲击回车后,首先发生的事情是域名的解析:将我们的域名解析为ip地址。ip地址是一种在因特网上给主机编址的一种方式,有ip4,ip6两大类。简单的来说ip也就是我们主机的名字。我们请求的数据就是来ip所指向的主机的,一个主机只有ip地址,而这个ip下可以有甚多域名的:因为一个ip对应一台主机,而一个域名对应了一个网站,而网站对应了一台主机里许许多多的文件和程序。
当然了解析域名并不是一个马上就完成的过程,解析的时候浏览器(以谷歌为例)会查看本身的DNS缓存,如果没有缓存,或缓存失效,就会继续搜索操作系统的DNS缓存,如果再找不到就会在本地的host文件内寻找缓存。如果也没有就会通知宽带运营商去查看自身缓存,若没有的话,宽带运营商会代替浏览器发送迭代的DNS解析请求,从根域(.com)开始找域名的DNS服务器,一直到子域名,当找到后,运营商会把结果返回给操作系统缓存起来。操作系统把结果再返回给浏览器。最终得到了URL的IP地址。
在拿到了IP地址后,就会发生经典的三次握手的过程了!
第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SENT状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。
第二次
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。
简单来说就是:客户端请求,服务器确认,服务器返回请求,客户端确认。
从逻辑上来讲,远处通信的两个人确认通信最符合逻辑的就是通过3此对话,少一次,多一次都会很奇怪:
2次:你听得到我吗? 听得到!你听得到我吗? blablabalbla。。 谁在讲话,是他么。。。。
4此:你听得到我吗? 听得到!你听得到我吗? 听得到!你听得到我吗? 呵呵。。。
好的!那么穿过了层层路由建立好了TCP连接之后,浏览器就能够拿到我们的HTML界面,在解析HTML内的静态资源时还需要分别发起一个个HTTP请求。最终把我们的界面渲染出来!
(关于四次挥手断开连接这里就不赘述了)
那么HTTP请求包含些什么呢?
谷歌浏览器给了我们很好的观察手段。。就是右键以后的network。
network模块把一个网页的整个加载的过程都展示了出来。
在控制台中,一共有 XHR(ajax请求),JS,CSS,Img,Media,Font,Doc,WC,Manifest,
other这些文件的类型。我们点进去后可以看到HTTP的内容了。
HTTP请求包含有请求头和正文信息。请求后服务器会返回信息。
请求头中有:
请求的URL地址、请求的方式、请求的状态码(status)200(成功),对应的ip地址。
当然还包括有:cookie,form data(表带数据)等
响应头中有:
HTTP版本号,请求方式,日期,cache-control,content-Encoding,Date,server,Vary,有无压缩等等。
Timing会显示这次请求的用时:
stalled:从可以发出到发出所等待的时间
proxy negotiation:代理协商时间
request sent:请求发出到结束的时间
waiting:发出请求到收到相应的时间
Content Download:收到相应到接收完最后一个字节的时间
DNS lookup:DNS解析时间

我们请求的方法有GET POST PUT DELETE HEAD TRACE OPTIONS
GET:读,获取。
POST:提交。
PUT:更新资源
DELETET: 删除指定数据
HEAD:只请求头部信息
状态码:1XX:接收了在处理
2XX:接收了请求而且处理完成
3XX:重定向,完成请求需要完成跳转之类的操作
4XX:有错误,语法错误,找不到页面等
5XX:服务器端有错误
200 OK
400 语法错误
401 没有授权
403 服务器拒绝服务
404 没找到资源
500 服务器发生了错误
503 当前无法处理该请求

HTTP进阶

关于进阶就有一系列的问题了:
什么是回调?
什么是同步/异步?
什么是I/O?
什么事单线程多线程?
什么是阻塞/非阻塞?
什么是事件?
什么是事件驱动?
什么事基于事件驱动的回调?
什么是事件循环?
一一来讲。。。
callback是实现异步的一种方式。当需要按照顺序来执行异步逻辑的时候,一般采用后续传递的方式。也就是将后续逻辑封装在起始函数中作为参数,逐层去嵌套。让程序按照我们所期望的方式来走完整个流程。
那么什么是异步呢?那我们先理解一下同步。同步就是在任务流中,所有的任务都要按照固定的顺序去执行。即是JS文件可以并行下载,但是运行却总要按照一定的顺序来进行。(当一个JS中有死循环是时,那么浏览器就会卡死了。。)但是如果是异步的话呢?我们每个任务有一个或多个回调函数的话,前一个任务结束后不是进行后一个任务,而是执行回调的函数,后一个任务也不是等待前一个任务执行完才执行。程序的执行顺序与任务的排列顺序是不一致的是异步的。JS中最简单的异步函数是setTimeout,和setInterval。
什么是单线程呢?JS就是单线程的,浏览器无论什么时候只有一个线程在运行javascript程序。
而相对的,浏览器内核是多线程的,它们在内核控制下相互配合保持同步,一个浏览器至少实现三个常驻的线程:JS引擎线程,GUI渲染线程,浏览器事件触发线程。JS引擎是基于事件驱动单线程执行的,JS引擎一直等待任务队列中任务的到来,然后加以处理。GUI渲染线程负责渲染浏览器界面,当界面需要重绘或者引发回流时,该线程就会执行。GUI渲染线程和JS引擎是互斥的,当JS引擎执行时,GUI线程会被挂起,GUI更新会被保存在一个队列中等到JS引擎空闲时被执行。事件触发线程是:当一个事件被处罚时,该线程会把事件添加到待处理的队列的尾列中,等到JS引擎处理。这些事件可能来自setTimeout,也可能来自浏览器内核的其他线程,比如鼠标点击,AJAX异步等等。但是由于JS单线程的关系,所有的时间都要排队等待JS引擎来处理。
如果要比喻的话,单线程是一条竖线,为了让这条线更短(更效率)我们要用异步去排列事件,把这条线折叠,让它最短,而多线程则是直接把这条竖线砍断,把它排成一行。他们各有各的优点,各有各的缺点。
什么是I/O呢?input/output。这个很好理解是磁盘的写入和读出,数据的进和出。以nodejs为例,nodeJS提供了I/O的接口,当非阻塞的结构准备好时,不用等待硬盘。那什么是非阻塞和阻塞呢?就是,不能够回调,不允许事件去排列,那一条线只能是这一条。这种模型就是阻塞的,事件遇到等待只能等,不能另辟蹊径了。
那么最后什么是事件什么事件驱动呢?基于事件驱动的回调?
这个就可以看看addEventListener了,非常熟悉吧!为事件去注册回调就是事件驱动啦!
那么事件循环呢?
EventLoop。当异步函数执行时,会将事件压入队列,队列中的函数按照顺序执行,但是回调函数是附属在
队列中的函数中的。eventloop就是由我们的回调函数所组成的一个附属线程,它使得主线程的更加效率,也就是直线变短了!

结语

HTTP内容牵扯到TCP,或者请求内容的一些详细细节就会发散开来了~这里就先总结一些基础吧!下一篇谈一谈深复制把!也就是引用对象的深复制。