HTTP协议
Posted ohana!
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HTTP协议相关的知识,希望对你有一定的参考价值。
目录
前置
1.网络划分
1)局域网
局域网,简称LAN,是指在某一区域内有多台计算机互联组成的计算机组,这些主机就可以互相通信,互相访问对方提供的资源
2)广域网
广域网,简称WAN,大家公认的开放的网络,连接上的主机都能访问
2.IP地址和端口号
1)IP地址
标识网络上某个主机的网络地址
格式:四个部分,每个部分之间用 . 分隔,每个部分0-255(8个比特位,一个字节)
本机IP:127.0.0.1
2)端口号
标识网络通信中,某个主机的某个进程
结合IP和port就可以知道要获取,网络上哪个主机的哪个进程
通俗点讲:IP地址就像是一个街道,让你直到具体在哪个街道(哪个主机),然而,端口号就像是门牌号,告诉你是哪家(哪个进程)
3.网络通信
通过网络,获取网络上某个主机的某个进程(资源)
一,概念
1.HTTP
HTTP协议也称“超文本传输协议”,是一种应用非常广泛的应用层协议
- 所谓 "超文本" 的含义, 就是传输的内容不仅仅是文本(比如 html, css 这个就是文本), 还可以是一些其他的资源, 比如图片, 视频, 音频等二进制的数据
2.二进制数据和文本
文本是带编码的二进制数据,两者其实是可以相互转化的,http是属于文本格式,内部可以包含一些二进制数据
1)在Java中,String有getByte("编码")就可以将字符串转化为二进制数据
2)new String(字节数组,"编码"),就可以将二进制数据转化为字符串
二,抓包
1.网络抓包
网络通信时,抓取传输的请求和相应的数据包
1)开发者工具:没有http协议原生格式的内容
2)fiddler:可以看到http原生格式的数据包
2.URL(统一资源定位器)
标识网络中,某个资源的路径(俗称网址),它具有全球唯一性,正确的URL才可以打开此网页
https://www.baidu.com/personInf/student?userId=10000&classId=100
(1)https(协议)
指定使用的传输协议,最常用的是HTTP协议,它也是WWW中应用最广的协议。
(2)www.baidu.com
服务器路径,可以使用IP,也可以使用域名
本机ip:127.0.0.1
本机域名:localhost
(3)端口号
浏览器不输入端口号:http协议默认使用80端口号,https默认使用443端口
(4)带层次的资源路径
标识在某个服务器中,具体某个资源的路径,如果没有输入资源路径,就是访问/
(5)查询字符串:querystring
起的作用就是获取某个资源下的不同的数据
格式:键值对格式,键=值,多个键值对之间用&间隔
key1=value1&key2=value2
注意:
- 如果URL中包含特殊字符,中文,空格等,都会转义,再放在http协议的数据包中,发送http请求
- urlencode(url编码):将里面的中文,空格等转换为16进制
- urldecode(url解码):将url中16进制数据转换为原始的中文,空格等
URL 中的可省略部分
- 协议名: 可以省略, 省略后默认为 http://
- ip 地址 / 域名: 在 HTML 中可以省略(比如 img, link, script, a 标签的 src 或者 href 属性). 省略后表示服务器的 ip / 域名与当前 HTML 所属的 ip / 域名一致.
- 端口号: 可以省略. 省略后如果是 http 协议, 端口号自动设为 80; 如果是 https 协议, 端口号自动设为 443.
- 带层次的文件路径: 可以省略. 省略后相当于 / . 有些服务器会在发现 / 路径的时候自动访问/index.html
- 查询字符串: 可以省略
- 片段标识: 可以省略
三, http协议格式
1)首行
- 请求行:请求方法 url http版本号
- 响应行/状态行:http版本号 状态码 状态码描述
2)header头
- 包括请求头/响应头:标识具有http协议的属性
- 格式:key: value(n对键值对,n对键值对之间用换行符间隔,冒号后边最好有一个空格)
- 在http协议中,有标准的header键,但是程序员也可以约定header键
3)空行
header家属,一直读取到空行,就可以解析到header
提问:为什么要有空行?空行存在的作用/意义?
因为 HTTP 协议并没有规定报头部分的键值对有多少个. 空行就相当于是 "报头的结束标记", 或者
是 "报头和正文之间的分隔符".HTTP 在传输层依赖 TCP 协议, TCP 是面向字节流的. 如果没有这个空行, 就会出现 "粘包问题"
4)body
请求正文/响应正文:请求携带的数据
四,请求方法
1)概念
标识具体是以什么方式来操作资源:获取/保存/修改/删除等(操作资源的类型)
2)GET
- GET 是最常用的 HTTP 方法. 常用于获取服务器上的某个资源.
- 在浏览器中直接输入 URL, 此时浏览器就会发送出一个 GET 请求.
- 另外, HTML 中的 link, img, script 等标签, 也会触发 GET 请求.
- 使用 javascript 中的 ajax 也能构造 GET 请求
- 获取资源(不一定遵守)
- 在浏览器地址栏中输入url,默认是GET请求方法
- 携带数据:使用queryString存放
- body(约定为空)不一定遵守
3)POST
- POST 方法也是一种常见的方法. 多用于提交用户输入的数据给服务器(例如登陆页面).
- 通过 HTML 中的 form 标签可以构造 POST 请求, 或者使用 JavaScript 的 ajax 也可以构造 POST 请求
- 提交数据到服务端
- 不使用queryString(不一定遵守)
- 使用body
4)其他方法
- PUT 与 POST 相似,只是具有幂等特性,一般用于更新
- DELETE 删除服务器指定资源
- OPTIONS 返回服务器所支持的请求方法
- HEAD 类似于GET,只不过响应体不返回,只返回响应头
- TRACE 回显服务器端收到的请求,测试的时候会用到这个
- CONNECT 预留,暂无使用
5)url长度问题
浏览器和web服务器可以配置url的最大长度,如果没有配置,就是用默认的长度
常见问题:
实际 URL 的长度取决于浏览器的实现和 HTTP 服务器端的实现. 在浏览器端, 不同的浏览器最大长
度是不同的, 但是现代浏览器支持的长度一般都很长; 在服务器端, 一般这个长度是可以配置的
6) GET和POST的区别
(1)语义上:GET是获取资源//数据,POST是提交资源或数据(可以打破)
(2)存放的位置:GET放在queryString上,POST放在body(可以打破)
(3)GET具有幂等性,POST不具有幂等性(如果多次请求到的结果一样,就是具有幂等性)
(4)GET可以缓存,POST不可以缓存
- 关于语义: GET 完全可以用于提交数据, POST 也完全可以用于获取数据.
- 关于幂等性: 标准建议 GET 实现为幂等的. 实际开发中 GET 也不必完全遵守这个规则(主流网站都有 "猜你喜欢" 功能, 会根据用户的历史行为实时更新现有的结果.
- 关于安全性: 有些资料上说 "POST 比 GET 请安全". 这样的说法是不科学的. 是否安全取决于前端在传输密码等敏感信息时是否进行加密, 和 GET POST 无关.
- 关于传输数据量: 有的资料上说 "GET 传输的数据量小, POST 传输数据量大". 这个也是不科学的, 标准没有规定 GET 的 URL 的长度, 也没有规定 POST 的 body 的长度. 传输数据量多少,完全取决于不同浏览器和不同服务器之间的实现区别.
- 关于传输数据类型: 有的资料上说 "GET 只能传输文本数据, POST 可以传输二进制数据". 这个也是不科学的. GET 的 query string 虽然无法直接传输二进制数据, 但是可以针对二进制数据进行 url encode
5.header头
标识http数据包属性
常用的键:
1)Host
标识服务器地址(域名/IP + port)
2)Content-Length
标识body的长度,对方才能根据这个长度来解析
- 客户端发送请求给服务端,对方就是服务端
- 服务端发送请求给客户端,对方就是客户端
3)Content-Type
常见的格式
a)application/x-www-form-urlencoded: form 表单提交的数据格式.和queryString格式一样,这里的字段值,只能是简单的数据类型
title=test&content=hello
b)multipart/form-data: form 表单提交的数据格式(在 form 标签中加上enctyped="multipart/form-data" . 通常用于提交图片/视频(也可以是简单地数据类型)
c)image/jepg:指定具体的一个文件类型
d)application/json:请求和响应都常用,和js对象的格式差不多(只是键也需要加双引号)
"username":"张三",
"password":"123456",
"age":18
请求:一般就是输入一些内容后,提交数据到服务端
响应:一般就是服务端返回一些数据,客户端js代码获取响应数据,然后填充到html中
4)User-Agent(UA)
也就是常说的浏览器表示,比如pc,手机等
5)Referer
标识当前这次的http请求是从那个页面点击或者跳转过来的
6)Cookie(请求头)
- 一种客户端保存数据的技术
- 保存数据:由服务端响应的http数据包中,设置Set-Cookie(一个或多个),Cookie是和网站关联,不同的网站有不同的Cookie(保存的信息如账号等不同网站保存为本地不同的Cookie)
- 使用:浏览器在每次请求时,自动携带在请求Cookie头中
- 格式:多组键值对(键=值,多个键值对之间用分号间隔)
7)Set-Cookie(响应头)
8)Session
- 一种服务端保存数据的技术,由于HTTP协议是一种无状态协议,一次请求一次响应,服务端无法感知之前登录的用户(服务端没有保存用户状态)
- 在服务端使用一个Map<String,Session>的数据结构来保存用户信息,这里的String就像是sessioid,一个Session对象就是一个用户会话,里面可以存放一个用户的需要保存的很多信息,这里的Sessio也是一个Map<String,Object>的结构,至于存放什么样的键值对数据,后端程序员实现
9)补充(关于Session和Cookie的时间)
Session:
- 服务端保存的Session信息,有默认的过期的时间(也可以通过程序设置)
- 服务器有session过期检验机制:通过单独的一个线程来扫描,发现当前时间和session最后一次使用的时间超时,就删除掉
- 服务端默认存放session的地方,web服务器默认是放在内存中,所以重启服务器,session也就没了(有些web服务器把数据存放在硬盘中,重启就还有)
- 注销后,时间超时后,重启后,服务端保存的session就没有了
Cookie:
- Cookie也有过期时间(可以通过程序来设置)
- 若Cookie过期,浏览器就找不到相应的令牌,就相当于无法验证
五,HTTP响应状态码
1.状态码
三位数字构成,标识服务端对客户端这次请求的处理结果,HTTP响应报文,都是服务端返回的,状态码也可以由程序设置
2.状态码(200)
- 标识服务端对当次请求处理成功(约定的规范)
- 如果程序有bug,出现异常,应该返回其他的状态码,但返回了200,就需要程序员去检查后端代码逻辑
3.状态码(301)
301:Moved Permanently:永久重定向
4.状态码(302)
302:Moved temporarily:临时重定向(和301看起来效果一样)
5.状态码(304)
304:Not Found:标识之前已经访问过的资源
- 本次请求的资源,没有被修改过,内容为空
- 如果服务端的资源没有变化,这样就节省了传输数据流量
- 当服务器代码发生改变或者重启服务器时,则重新发出资源
- 当服务器有变化时,客户端能得到最新的资源
6.状态码(307)
307也是临时重定向,和302的区别是:
307要求客户端不改变原先的请求方法,对在Location头部中规定的uri进行访问,对于,302,很多客户端的实现是,直接使用get方式访问重定向地址
7.状态码(403)
403:Forbidden:禁止访问,一般有两种情况
- 未登录去访问
- 登录后,权限不足
8.状态码(404)
404:Not Found:标识请求的url路径没有对应的资源
url的格式:[协议名]//:[ip或域名]:[port]/[带层次的路径]?[查询字符串]
找不到主机,或者找不到进程(port),找不到资源路径
9.状态码(405)
405:Method Not Allowed:方法不支持
服务端提供的方法是一个或者多个,请求的方法没在服务提供的方法范围内,返回405
- 如果出现405,要检查是前端的请求方法不对还是后端提供的方法不对
10.状态码(500)
500:Internal Server Error:服务器内部错误
一般是服务器内部代码有问题,出现异常等,如果出现,一定要检查后端的堆栈信息,定位后端的代码问题
11.状态码(504)
504:Gateway Timeout:请求在服务端处理超时
- 服务端也有时间限制(可以设置),发现处理时间超过这个时间就返回504(如果请求过多,并发高问题,处理不过来,还可能是程序效率低)
- 客户端请求也是有时间限制的,如果服务端没有在时间限制内返回,就报错
六,Ajax
1.form构造http请求
<body>
<!-- form表单提交数据到服务端:action是请求的url,method是请求方法 -->
<!-- get方法默认请求数据放在queryString,post方法默认是body上 -->
<!-- post默认提交方式(Content-Type)为表单格式(application/x-www-form-urlencoded) -->
<form action="http://abc.com" method="get">
<!-- 表单中的控件(文本框,密码框,单选复选框,下拉菜单等)都以name为键,用户输入/选择
的内容为值 -->
<!-- 键=值,多个之间 & 间隔 -->
<input type="text" name="username">
<input type="password" name="password">
<input type="submit" value="提交">
</form>
</body>
2.Ajax构造get方法
<script>
// XMLHttpRequest对象就是ajax发送请求及处理响应的对象
let xhr = new XMLHttpRequest();
// 设置一个异步回调函数到ajax对象的属性中
// 注意:这里只是函数的声明,不会执行,而是发送http请求,对应的事件发生,才调用回调函数
xhr.onreadystatechange = function()
// xhr.readyState属性:
// 0: 请求未初始化:还没发送http请求
// 1: 客户端和服务器的连接已建立:
// 2: 服务端已接收请求
// 3: 服务端正在处理请求
// 4: 客户端已收到服务端返回的响应,且响应已就绪
if(xhr.readyState == 4)
// xhr.status属性:响应状态码
console.log(xhr.status);
// xhr.responseText属性:响应正文
console.log(xhr.responseText);
// open:设置请求方法和url,此时还没有发送http请求
xhr.open("GET", "http://42.192.83.143:8089/AjaxMockServer/info");
// send:正式发送http请求,也可以设置请求正文(body)数据
xhr.send();//send(), send(body)两种方式
</script>
3.Ajax构造post方法
<script>
// XMLHttpRequest对象就是ajax发送请求及处理响应的对象
let xhr = new XMLHttpRequest();
// 设置一个异步回调函数到ajax对象的属性中
// 注意:这里只是函数的声明,不会执行,而是发送http请求,对应的事件发生,才调用回调函数
xhr.onreadystatechange = function()
// xhr.readyState属性:
// 0: 请求未初始化:还没发送http请求
// 1: 客户端和服务器的连接已建立:
// 2: 服务端已接收请求
// 3: 服务端正在处理请求
// 4: 客户端已收到服务端返回的响应,且响应已就绪
if(xhr.readyState == 4)
// xhr.status属性:响应状态码
console.log(xhr.status);
// xhr.responseText属性:响应正文
console.log(xhr.responseText);
// open:设置请求方法和url,此时还没有发送http请求
xhr.open("POST", "http://42.192.83.143:8089/AjaxMockServer/info");
// 设置请求头
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");//设置请求数据
格式/类型
// send:正式发送http请求,也可以设置请求正文(body)数据
xhr.send("username=abc&password=123");//send(), send(body)两种方式
</script>
4.Ajax封装
<script>
// 封装一个ajax函数,参数args为一个js对象
// 定义args对象属性如下:
// method: 请求方法
// url: 请求服务器资源的路径
// contentType: 请求正文的格式
// body: 请求正文
// callback: 回调函数,客户端接收到响应数据后,调用
function ajax(args)//var ajax = function()
let xhr = new XMLHttpRequest();
// 设置回调函数
xhr.onreadystatechange = function()
// 4: 客户端接收到响应后回调
if(xhr.readyState == 4)
// 回调函数可能需要使用响应的内容,作为传入参数
args.callback(xhr.status, xhr.responseText);
xhr.open(args.method, args.url);
//如果args中,contentType属性有内容,就设置Content-Type请求头
if(args.contentType)//js中,if判断,除了判断boolean值,还可以判断字符串,对象等,有值就为true
xhr.setRequestHeader("Content-Type", args.contentType);
//如果args中,设置了body请求正文,调用send(body)
if(args.body)
xhr.send(args.body);
else//如果没有设置,调用send()
xhr.send();
//调用ajax封装的函数
//方法一:
let request =
method: "POST",
url: "http://42.192.83.143:8089/AjaxMockServer/info",
contentType: "application/x-www-form-urlencoded",
body: "username=abc&password=123",
callback: function(status, response)//调用的时候传入了两个参数,定义对应的参数
console.log("响应状态码:"+status+",响应正文:"+response)
;
ajax(request);
//ajax函数调用的json对象参数,也可以不声明,直接传入函数
//方法二:
// ajax(
// method: "POST",
// url: "http://42.192.83.143:8089/AjaxMockServer/info",
// contentType: "application/x-www-form-urlencoded",
// body: "username=abc&password=123",
// callback: function(status, response)//调用的时候传入了两个参数,定义对应的参数
// console.log("响应状态码:"+status+",响应正文:"+response)
//
// );
</script>
以上是关于HTTP协议的主要内容,如果未能解决你的问题,请参考以下文章
IIS7.5上的REST服务的Put操作发生HTTP Error 405.0 - Method Not Allowed 解决方法