浏览器如何定位一台服务器?
使用url统一资源定位符:protocal://hostname:port/path?query#hash
- protocal: 协议,服务器根据不同的协议确定数据交换的格式和方式,常用的有
http
和https
; -
hostname: 主机名,可以是ip,也可以是域名;
- ip:网络中每个终端的唯一编号;
- 域名:和ip一一对应,方便记忆;
- 域名和ip的关系:计算机是通过ip在网络上查找的另一台计算机,域名是方便人阅读和记忆。输入域名的时候,计算机会先去通过域名解析服务器(DNS)将域名转化成ip,再去网络中根据这个ip查找计算机。
-
port:端口号,服务器中有很多其它的应用,端口是用来定位使用服务器中的哪一个应用;
- http: 默认端口
80
- https:默认端口
443
- http: 默认端口
- path:路径,用于区分使用web服务器的哪个服务。
-
query:查询参数,用于向web服务器传递信息。
url只支持ASCII字符,输入中文会被转义
- hash:锚点,定位页面中的内容,唯一一个改变后浏览器不会重新访问服务器的值(不会刷新页面),可以用来做路由。
浏览器和服务器传输数据的格式是什么?
http是其中一种用来规定浏览器和服务器传输数据格式的协议。
http将浏览器和服务器之间的一次交互分为两个部分:
- 请求request:客户端发生数据给服务器的过程
- 响应response:服务器收到请求返回一个数据给客户端的过程
其实一个请求可以看做是一个规定了格式的特殊字符串,下面我们看看这个字符串是有什么组成的。
以百度的网址为例,
请求request由请求头和请求体两个部分组成:
1. 请求头(request headers)
规定请求的请求方式,就是告诉服务器自己给什么格式的数据,以什么方式给,希望返回什么数据等。
GET /s?wd=abc HTTP/1.1
Host: www.baidu.com
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36
Sec-Fetch-User: ?1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cookie: PSTM=1563287690;
请求头又包括请求行和其它属性:
-
请求行:请求头的第一行
- 请求方法:GET、POST等
- path:url中的path + search + has
- 协议及版本号:HTTP/1.1
-
其它属性:后面的数据以键值对的形式存储,可以自定义
- Host: 主机名
- Connection: 连接方式
2. 请求体(request body)
- 请求体就是浏览器要发送给服务器的数据,一般是服务器需要用到的业务数据。
-
请求头中也可以传递不同格式的数据,一般由请求头中的
Content-Type
属性来描述请求体中使用的格式。-
常见的格式:
-
application/x-www.form-urlencoded
对应的数据格式:属性名=属性值&属性名=属性值 -
application/json
对应的数据格式:{"属性名":"属性值", "属性名":"属性值"} -
multipart/form-data
对应的数据格式:使用某个随机字符串作为属性之间的分隔符,通常用于文件上传。
------WebKitFormBoundaryD1o3TzulmXAIABD2 Content-Disposition: form-data; name="image"; filename="xxx.png" Content-Type: image/png ------WebKitFormBoundaryD1o3TzulmXAIABD2--
-
-
响应response由响应头和响应体两个部分组成:
1. 响应头(response headers)
服务器根据请求头和请求体构建出来的数据,告诉客户端响应的状态,响应数据的格式等信息。
HTTP/1.1 200 OK
Content-Length: 24
Content-Type: text/plain; charset=UTF-8
Date: Mon, 03 Feb 2020 10:21:37 GMT
响应头又包括响应行和其它属性:
-
请求行:请求头的第一行
- 协议及版本号:HTTP/1.1
- 状态码:对应不同的响应状态
- 状态文本:用于描述状态码的文本
常见的状态码:
200: 请求成功。
301:资源永久重定向,告诉浏览器这个资源已经不在当前地址了,去其它地方取,其它地方的地址一般放在Location属性中。
302:资源临时重定向,告诉浏览器这个资源没有变化,自己去缓存中拿。
400:请求有问题,当前请求服务器无法识别。
403:服务器拒绝执行,可能是权限不够造成的,服务器不返回数据。
404:页面找不到,告诉浏览器这个地址不对,我这里找不到对应的资源。
500:服务器内部错误,表示是服务器处理程序出错。
502:网关错误,浏览器请求的地址可能还会进行一层网关的过滤,用来分发到不同的服务器,网关错误表示代理网关无法从上游服务器获取数据。
503:服务器过载,表示当前服务器处理不了那么多请求,拒绝当前浏览器发出的请求,一般会在响应头添加一个Retry-After属性。
504:网关超时,网关请求上游服务器一般会设置的一个时间限制,在规定时间内没有从上游服务器获取数据就会产生该错误信息。
-
其它属性:后面的数据以键值对的形式存储,可以自定义
- Server: web服务器类型,Apache、IIS等
- Content-Type: 描述响应体中的数据格式
2. 响应体(response body)
服务器返回给客户端的业务数据
常见的数据格式有:
-
text/plain
:普通的存文本。浏览器会原封不动的显示在页面上。 -
text/html
:html文档,浏览器会将返回的数据解析成页面。 -
text/css
:css代码,浏览器会根据返回数据渲染html页面。 -
text/javascript
:js代码,浏览器会启动js引擎进行解析。 -
attachment
:附件、浏览器看到该属性会自动下载服务器返回的数据。 - 其它MIME类型
POST请求和GET请求的区别?
就协议的角度来讲是没有什么实质的区别,不管是那种请求都是由请求头和请求体组成的,只不过服务器会根据请求的方式不同去不同的地方读取业务数据。
服务器对于不同的请求方法做出的处理(不是绝对的,开发者可以自己处理)
- GET请求:服务器遇到GET请求一般会去path中读取数据。
- POST请求:服务器遇到POST请求一般会去请求体中读取数据。
浏览器对于不同请求做出的处理
- GET请求会限制url大小,因此如果业务数据过大要使用POST请求。
- POST请求只能通过表单的形式提交,在浏览器地址栏输入的url都是以GET的方式向服务器发送请求。
其它差异:
- GET请求会保留请求数据,利于用户做分享。
- GET请求的业务数据是放在url中的,一般带有用户信息的数据都不应该使用GET请求,防止被其它人偷窥,或者被用户自己分享出去。
什么是Ajax?
AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。
是浏览器提供给js的请求网络数据的API。
请求实例:
var xhr = new XMLHttpRequest(); //创建请求实例
// 监听请求变化的函数
xhr.onreadystatechange = function (response) {
if (xhr.readyState === 4 && xhr.status === 200) { //表示所有内容接受完毕,并且服务器返回的状态是请求成功
console.log(xhr.responseText);
}
}
xhr.open("GET", "https://api.binstd.com/shouji/query"); //配置请求
xhr.send(); //构建请求体,发送请求体
现在大部分的请求都使用fetch替代ajax。(fetch是es6提供的请求网络数据的新API,用promise封装的网络请求API。)
什么是跨域?
- 协议,域名,端口三者有一个不同就会造成跨域无法获取数据的问题;
- 跨域是浏览器为了提高安全性做的限制。只有在浏览器中才会发生的现象。服务器之间互相访问是不会出现跨域问题的;
-
link
、img
、script
等含有src
属性的标签也不会出现跨域问题; - 解决跨域问题,有jsonp,后台设置运行跨域,iframe等方法;但是副作用最少,无需后台配合的就是自己写代理服务器。
代理服务器
服务器代理解决跨域问题思路:
- 出现跨域问题一般是请求不同域下的资源,请求相同域中的资源不会出现跨域问题。
- 自己编写一个服务器,将要发请求的页面放在该服务器下,再通过自己的服务器请求真实接口,将返回的数据回传给页面就可以解决跨域问题。
代理服务器的作用:你请求有跨域问题,我请求不会,我帮你请求再把数据返回给你。
举个例子:
环境:node
v10.16.0,yarn
1.15.2
目录结构:
- demo.html
- proxy.js
-
在项目根目录打开
cmd
,运行命令:yarn init yarn add express yarn add request
-
新建
demo.html
文件,代码如下:<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>测试跨域请求</title> </head> <body> <script> var xhr = new XMLHttpRequest(); //创建请求实例 // 监听请求变化的函数 xhr.onreadystatechange = function (response) { if (xhr.readyState === 4 && xhr.status === 200) { //表示所有内容接受完毕,并且服务器返回的状态是请求成功 console.log(JSON.parse(xhr.responseText)); } } xhr.open("GET", "http://localhost:2020/api"); //配置请求 xhr.send(); //构建请求体,发送请求体 </script> </body> </html>
-
新建
proxy.js
文件,代码如下:var express = require('express'); //导入express模块 var request = require('request'); //导入request模块 var app = new express(); //创建express实例 app.use(express.static('./')); //监听文件夹,获取静态资源 app.listen(2020); //监听2020端口 //监听api接口 app.get('/api', function (req, res) { // 请求真实接口 request('https://api.binstd.com/shouji/query', function(error,response,body){ res.header('Content-Type', 'application/json;charset=utf-8'); res.send(body); //返回数据 }) })
- 启动服务器,在
cmd
输入node proxy.js
。 - 打开浏览器,输入网址:
http://localhost:2020/demo.html
,查看控制台,现在就不会有跨域问题产生。
什么是三次握手?
客户端与服务器建立TCP/IP连接的准备阶段进行的三次交互被称为三次握手。
http协议是基于TCP/IP协议建立的数据传输协议,http定义的是数据收发双发的格式,TCP/IP协议定义的是数据接收时连接怎么建立。
过程:
- 客户端向服务器发送请求;
- 服务器接收请求,向客户端发送回应;
- 客户端接收回应;
为什么要进行三次握手?
为了建立一个可靠的连接,确保客户端和服务器都具备收发能力。
分析:
假设只进行步骤1,客户端向服务器发送请求,客户端无法知道服务器真的能接到消息;
假设进行了步骤1,2,客户端知道服务器具备收数据的功能,服务器也知道客户端具备发数据的功能,但是服务器还不能确定客户端是否能收到数据;
所以要执行步骤3,这就是为什么一定要三次握手。
什么是四次挥手?
四次挥手是TCP/IP连接断开时候客户端和服务器进行的四次交互过程。
过程:
- 客户端发送中断请求,不再发送数据;
- 服务器接收中断请求,数据没发送完成,还可以发送数据;
- 服务器发送关闭连接请求 ,不可发送数据;
- 客户端确定关闭连接。
发完了,知道发完了,收完了,知道收完了
为什么要进行四次挥手?
为了确保在断开连接之前客户端和服务器的交互数据已经收发完毕。
分析:
- 客户端告诉服务器我要断开连接,不再发送数据;
- 服务器知道了客户端要断开请求,但是还有数据要发个客户端,告诉客户端先等我的数据发完再断开连接;
- 过了一会服务器数据发送完毕,服务器告诉客户端数据发完了,可以关闭连接了(此时服务端不再接收客户端消息);
- 客户端收到通知,关闭连接,不再接受服务端消息。完成整个断开连接过程。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。