HTTP协议

应用层的一些基本概念

网络初始,我们认识了网络的协议栈,TCP/IP分为五层:应用层,传输层,网络层.数据链路层,物理层

应用层是程序员打交道最多的层次,应用层涉及到的网络通信协议,很多都是程序员自定制的

应用层涉及到的网络通信协议.很多都是程序员自定制的,那我们如何自定义协议呢?

自定义协议分为两个阶段:根据需求明确传输哪些信息,明确好信息传输的格式

信息传输的格式:

1)行文本的形式 名字,名字(这种现在已经不怎么用了)

2)通过xml格式来约定,请求和响应的格式

html和xml都是成对的标签构成的键值对结构

html标签内容都是固定的,不能乱写,也不能创建新的标签(现在html5运行自定义标签了)

xml标签内容自定义(用于网络传输,和浏览器怎么显示无关,html约定浏览器怎么显示)

xml方案 现在也很少用了,优点:可读性好 缺点:冗余信息太多了,网络传输中消耗更多的带宽

3)json当下最流行的网络数据格式组织的方案

请求

{

"uesrId":1000,

"positon":"75E75N"

}

优点:可读性好,消耗的带宽也相对少

缺点:存在冗余信息

4)protobuf

基于二进制的形式,对数据进行压缩,不涉及json和xml冗余信息,带宽消耗少了,可读性变差了

适合于性能要求高的场景,用开发效率换执行效率(比较少)

应用层除了自定义协议之外,也有一些已经搞好的协议

FTP文件传输/SSH远程操作主机/telnet网络调试工具...HTTP协议[重点]

这里我们要介绍应用层的一个主要协议HTTP

HTTP协议

HTTP是什么?

HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议

HTTP一问一答模式的协议 请求和响应一一对应 网络通信中也有其他的模型(一问一答,上传大文件,一问多答,下载大文件,多问多答 )

浏览器打开网页的场景/手机app加载数据都是常见的一问一答的场景 使用HTTP就非常合适

HTTP报文格式

抓包工具

抓包工具能够获取到网络的数据包,详细的格式都解析出来(抓包工具就相当于"代理"),代理分为:正向代理(代表客户端干活) 反向带来(代表服务器干活)

软件 电脑上所有的通信,都会先发给这个抓包程序,抓包程序再把数据转发给服务器

常见的抓包工具:wireshark fiddler

(wireshark可以抓很多协议,HTTP/TCP/UDP/IP,以太网数据帧,使用起来门槛高,比较麻烦,新手入门我们推荐fiddler)

HTTP协议格式总结

请求:

1.首行 方法 url 版本号

2.请求头 键值对

3,空行

4.正文

响应:

1.首行 版本号 状态码 状态码描述(非常重要 开发/调试)

2.响应头

3.空行

4.正文

HTTP请求(Request)

认识URL

URL基本格式

平时我们俗称的网址其实就是说的URL(Uniform Resource Locator 统一资源定位符)

互联网上的每个文件都有一个唯一的URL,他包含的信息指出文件的位置以及浏览器应该怎么处理他

一个具体的URL:

http://user:pass@www.example.jp:80/dir/index.htm?uid=1#ch1

hhtp 协议方案名 user:pass 登陆信息(认证) www.example.jp 服务器地址

80服务器端口号 dir/index.htm 带层次的文件路径 uid=1 查询字符串

ch1片段表示符

URL可以省略部分

协议名:可以省略,省略后默认为http://

ip地址/域名:在HTML中可以省略(比如 img,link,script,a标签的src 或者href属性).省略后表示服务器的ip/域名与当前HTML所属的ip/域名一致

端口后:可以省略,省略后如果是http协议,端口号自动设为80;如果是https协议,端口号自动设置为443

带层次的文件路径:可以省略.省略后相当于/. 有些服务器会在发现/路径时候自动访问/index.html

查询字符串:可以省略

片段标识:可以省略

关于URL encode

像/ ? :等这样的字符,已经被url当做特殊意义理解了.因此这些字符不能随意出现

比如,某个参数中需要带有这些特殊字符,就必须先对特殊字符进行转义

转义的规则如下:将需要转码的字符转为16进制,然后从右到左,取4位(不足4位直接处理),每2位做一位,前面加上%,编码成%xy格式

urldecode就是urlencode的逆过程

认识方法

|---------|-------------|-------------|
| 方法 | 说明 | 支持的HTTP协议版本 |
| GET | 获取资源 | 1.0,1.1 |
| POST | 传输实体主体 | 1.0,1.1 |
| PUT | 传输文件 | 1.0,1.1 |
| HEAD | 获得报文首部 | 1.0,1.1 |
| DELETE | 删除文件 | 1.0,1.1 |
| OPTIONS | 询问支持的方法 | 1.1 |
| TRACE | 追踪路径 | 1.1 |
| CONNECT | 要求用隧道协议连接代理 | 1.1 |
| LINK | 建立和资源之间的联系 | 1.0 |
| UNLINE | 断开连接关系 | 1.0 |

1.GET方法

GET是最常用的HTTP方法,常用于获取服务器上的某个资源

在浏览器中直接输入URL,此时浏览器也会发送出一个GET请求.另外,HTML中的link,img,script 等标签,也会触发GET请求

GET请求的特点:1.首行的第一部分为GET 2.URL的query string可以为空,也可以不为空

3.header部分有若干个键值对结构 4.body部分为空

GET请求的URL的长度问题:实际URL的长度取决于浏览器的实现和HTTP服务器端的实现,在浏览器端,不同的浏览器最大长度是不同的,但是现代浏览器支持的长度一般都很长,在服务器端,一般这个长度是可以配置的

2.POST方法

POST方法也是一种常见的方法,多用于提交用户输入的数据给服务器(例如登陆页面,上传=>(请求带有正文,正文就是保存了当前上传的数据的内容))

通过HTML中的form标签可以构造POST请求,或者使用js的ajax也可以构造POST请求

POST的请求的特点:1.首行的第一部分为POST 2.URL的query String一般为空(也可以不为空)

3.header部分有若干个键值对结构 4.body部分一般不为空,body内的数据格式通过header中的Content-Type制定,body的长度由header中的Content-Length指定

get和post的区别:

1.语义不同:GET一般用于获取数据,POST一般用于提交数据

2.GET的body一般为空,需要传递的数据通过query string传递,POST的query string一般为空,需要传递的数据通过body传递

3.GET请求一般是幂等的,POST请求一般是不幂等的(如果多次请求得到的结果一样,就视为请求是幂等的)

4.GET设计成幂等的,就可以运行GET请求的结果被缓存 POST由于不要求幂等,经常是不幂等的,就认为不能被缓存

补充说明(一些有待商榷的问题)

1.POST比GET更安全

登陆场景,输入用户名和密码,GET用户名和密码就会放到url的query string,就会显示在浏览器地址栏上,但关键是"加密传输",只有明文传输,都谈不上安全

2.GET传输的长度有限制

上古时期,IE6对URL的长度是有限制的

3.GET只能传输文本,POST可以传输二进制

GET在url中只能放文本,可以把二进制通过base64转换为文本

GET也不是完全不能带body(有些客户端/服务器不支持)

3.其他方法

1.PUT与POST相似,只是具有幂等特性,一般用于更新

2.DELETE删除服务器指定资源

3.OPTIONS返回服务器所支持的请求方法

4.HEAD类似于GET,只不过响应体不返回,只返回响应头

5.TRACE回显服务器端收到的请求,测试的时候会用到这个

6.CONNECT预留,暂无使用

这些放的的HTTP请求可以使用ajax来构造(也可以通过一些第三方工具)

任何一个能进行网络编程的语言都可以构造HTTP请求,本质上就是通过TCP socket写入一个符合HTTP协议规则的字符串

认识请求"报头"(header)

header的整体格式也是"键值对"结构

每个键值对占一行,键和值之间使用分号分割

报头的种类有很多,这里介绍几个常见的

Host 表示服务器主机的地址和端口

Host:gitee.com:端口号 ip(域名)/端口号 表示请求访问的服务器在哪里

绝大部分情况下,这两属性是一致的,但也有一些场景式不一致的.比如,使用了代理(我们仍然可以通过Host来获取到最原始的目标是啥)

HTTP协议中,传输过程中可能会涉及到加密(HTTPS),url部分是不会被加密的,加密的部分是header和body

服务器收到请求之后也就可以做一个最终校验,URL内容和header中加密内容是否一致

Content-Length Content-Type

Content-Length 表示body中的数据长度 Content-Type表示请求的body中的数据格式 提示接受方如何解析body (这两个属性与是否有body有关)

HTTP协议,传输层这里是基于TCP实现的(版本号<=2.0) 所谓的HTTP协议,就是把字符串构造成HTTP约定的格式

Content-length:把一段字符串,写入到tcp socket中,对于TCP来说,一个连接上可以发送多个请求,服务器收到数据得区分一下,从哪里到哪里是一个完整的http请求数据

Content-Type:提示接收方如何解析body HTTP这里可以携带的数据种类比较多

|------|------------------------|
| HTML | text/html |
| CSS | text/css |
| JS | application/javascript |
| JSON | application/json |
| 图片 | image/png image/jpg |

请求和响应都会有这两个header,如果有body,没有同时有这两个属性 都认为是非法/错误的http报文

User-Agent(简称UA)

表示浏览器/操作系统的属性

例如这个例子中,Mozilla/5.0 表示firefox (Windows NT10.0...)表示操作系统版本

AppleWebKit/537.36表示浏览器内核 Chrome表示浏览器的版本

Safari表示苹果的浏览器

通过UA中的浏览器,操作系统版本,区分出当前用户的设备,最多都支持那些特性

另一个用途: 可以区分用户的设备 Windows/mac ->PC ios/Android->手机

根据用户的设备,返回不同版本的页面(通过CSS的"媒体查询",感知到当前窗口的尺寸,通过不同的尺寸,设置不同的样式)

Refer

表示这个页面是从哪个页面跳转过来的

用途:广告主通过refer这样的方式区分从哪个页面传过来的(refer也有可能被修改,HTTP->HTTPS)(HTTPS协议能够有效的对HTTP数据报进行加密传输(refer也有可能被加密了))

Cookie中存储了一个字符串,这个数据可能是客户端(网页)自行通过JS写入的,也可能来自于服务器(服务器在HTTP响应的header中通过set-Cookie字段给浏览器返回数据)

浏览器展示页面的过程中,页面虽然可以通过js来实现一些逻辑,但js代码无法访问你的硬盘(文件系统)

实际开发中,希望把某些数据保存到本地硬盘中,因此引入了Cookie机制,浏览器允许网页在本地硬盘存储数据的一种机制,不是让网页代码直接访问文件系统,而是做了一层抽象,浏览器的Cookie提供了键值对的存储机制

这里我们总结一下键值对(结合实际情况,基于HTTP实现一些个性化的功能需求)

|--------------------------|--------|
| url的query String | 程序员自定义 |
| header部分的键值对 | 规定 |
| header中Cookie里存储的数据也是键值对 | 程序员自定义 |
| body是json格式,仍然是键值对 | 程序员自定义 |

浏览器保存了Cookie后,就会在后续给服务器发送请求的时候,把这些Cookie键值对放到请求CookieHeader中传给服务器

Cookie从哪里去:最终发会给服务器 Cookie从哪里去:来自服务器(后端开发程序员决定的)

Cookie里的数据都是程序员自定义的,业务相关的,有一个典型的例子,属于"通过业务",登陆和用户验证

具体说明,当登陆页面发送登陆请求,会查询数据库,验证用户名密码是否有效 无效,登陆失败 有效:1.服务器这边会生成一个sessionID 2.并且生成session对象 3.把关键信息保存到session对象中 4.sessionID和session作为键值对,保存到内存的hash表中 5.把sessionID通过set-Cookie返回给浏览器(服务器收到后续请求后,直接同构Cookie的sessionID就可以知道请求是哪个用户发来的,就不用用户重新登陆)

Cookie是会过期的,安全性不高,过期时间就越长

HTTP响应

认识"状态码"(status code)

状态码表示访问一个页面的结果(是访问成功,还是失败,还是其他的一些情况)

常见的状态码:

200 OK 这是一个最常见的状态码,表示访问成功

404 Not Found 还没有找到资源 状态码即使有错的,也可以在body中返回一些html之类的(装扮404页面)

403 Forbidden 访问被拒绝(没有权限)

405 Method Not Allowed 请求的方法和服务器这边的声明的注解并不匹配.就会出现405(在后续学习Spring框架我们会学到很多注解)

500 Internal Server Error服务器出现内部出现错误,一般是服务器的代码在执行过程遇到了一些特殊情况(服务器异常崩溃)会产生这个状态码

504 Gateway Timeout 网关 网络的入口 在服务器资源紧张时容易触发

302 Move temporarily 临时重定向 (重定向:访问服务器A,服务器A告诉你去找B)

状态码小结

|-----|------------------|
| 类别 | 原因 |
| 1xx | 接受的请求正在处理 |
| 2xx | 请求正常处理完毕 |
| 3xx | 需要进行附加操作以完成请求 |
| 4xx | 服务器无法处理请求(客户端错误) |
| 5xx | 服务器处理请求出错 |

认识响应"报头"(header)

响应报头的基本格式和请求报头的格式基本一致

构造HTTP请求

通过format(表单构造HTTP请求)

form(表单)是HTML中的一个常用标签,可以用于给服务器发送GET/POST请求

form的重要参数: action:构造和HTTP请求的URL是什么 Method:构造的HTTP请求的方法是GET/POST(form只支持post和get)

input的重要参数: type:表示输入框的类型 text表示文本 password表示密码, submit表示提交按钮

name:表示构造的HTTP请求的query String的key query String的value就是输入框的用户输入的内容

value:input标签的值,对于type的submit类型来说,value就对应了按钮上显示的文本

通过ajax构造HTTP请求

从前端角度,除了浏览器地址栏能构造get请求,form表单能构造get/post之外,还可以通过ajax的方式来构造HTTP请求,并且功能更强大

ajax是javascript给服务器发送HTTP请求的方式,特点是可以不需要刷新页面/页面跳转 就能进行数据传输 ajax是js提供的api,原生的ajax比较难用,XMLHttpRequest类 后来有了个第三方库 :jQuery

通过Java Socket构造HTTP请求

HTTP请求本质上是TCP请求,只需要构造字符串,符合HTTP协议格式,写入到TCPSocket中

我们还可以通过postman等工具构造HTTP请求

HTTPS

什么是HTTPS

HTTPS=HTTTP+S(SSL/TLS)也是一个应用层协议,负责加密

加密就是把明文(要传输的信息)进行一系列变换,生成密文

解密就是把密文再进行一系列变换,还原成明文

在加密和解密的过程的,往往需要一个或多个中间的数据,辅助进行这个过程,这样的数据称为密钥

密钥:1.对称加密 加密和解密用一个密钥 2.非对称加密:加密使用一个密钥,解密使用另一个密钥(不存在关联关系,很难猜)

HTTPS的工作过程

引入对称加密

对称加密其实就是通过使用同一个密钥,把明文加密成密文,并且能把密文解密成明文

引入对称加密之后,即使数据被截获,由于黑客不知道密钥是啥,因此就无法进行解密,也不知道请求是啥 但真实情况并没有我们想的这么简单,一台服务器同一时刻其实是给很多客户端提供服务的,这么多个客户端,每个客户端的密钥必须是不同的,因此服务器需要维护每个客户端和每个密钥之间的关联关系(这是件非常麻烦的事情,如果客户端数量非常多,那么需要记忆的数据量是非常大的,即使我们可以存储这么多数据,但不同客户端访问的频率也不同,这是个非常低效的做法)

我们比较理想的做法,就是能在客户端和服务器建立连接的时候,双方协商确认这次的密钥是啥

但如果直接把密钥明文传输,那么黑客也就能够获得秘钥了,此时后续的加密就相当于没加了

于是就引入了非对称加密,就为了解决秘钥传输的安全性问题

引入非对称加密

非对称加密要用到两个秘钥,一个叫做"公钥",一个叫做"私钥"

公钥和私钥是配对的,最大的缺点就是的运算速度非常慢,比对称加密要慢很多

对称加密:运算速度快,开销小,适合针对大量数据加密

非对称加密:运算速度慢,开销大,加密小的数据还行,大的数据就会很耗时

当前这个场景有三个秘钥:1.客户端生成的对称密钥 2.服务器生成的公钥,可以给所有设备告知

3.服务器生产的私钥,只有自己知道

上述这样的流程存在重大安全隐患,黑客可以通过特殊手段,来获取到对称密钥,破坏后续传输的安全性

中间人攻击

为了避免中间人攻击,我们引进了校验机制.中间人攻击的关键在于客户端无法区分收到的公钥是否是服务器真实的公钥,还是黑客篡改的公钥,想办法能够验证公钥的正确性,我们使用证书来校验

校验和与数字证书的内容有关 生成校验和之后还要对校验和加密(数字签名起到验证身份的作用)

客户端收到证书就要进行校验

1.客户端要针对证书中的其他字段,使用相同的算法得到校验和1 2.再通过公正机构的公钥pub2,对数字签名进行解密得到校验和2 3.对比校验和1和校验和2是否相同,如果相同,说明证书是没有被修改的(客户端如何确保pub2是公证机构的pub2? pub2不是通过网络传输的,是操作系统内置的)

相关推荐
橘颂TA2 小时前
【Linux 网络】TCP 拥塞控制与异常处理:从原理到实践的深度剖析
linux·运维·网络·tcp/ip·算法·职场和发展·结构与算法
2401_873587823 小时前
Linux——应用层协议定制
linux·运维·网络协议
大榕树信息科技3 小时前
动环监控如何提升数据中心的运维效率和安全性?
运维·网络·物联网·机房管理系统·动环监控系统
你这个代码我看不懂3 小时前
Spring Boot拦截Http请求设置请求头
spring boot·后端·http
G31135422734 小时前
域名解析生效后网站为什么打不开?要怎么解决?
网络
ccieluo4 小时前
基于eNSP的中小型企业网络设计与实现
网络·毕业设计
zyxqyy&∞4 小时前
HCIP--BGP--1
网络·hcip
REDcker4 小时前
Socket 带宽上限详解
网络
遇见火星5 小时前
在Linux中使用parted对大容量磁盘进行分区详细过程
linux·运维·网络·分区·parted