应用层——典型协议解析

应用层典型协议

应用层的协议都是需要我们程序员根据需要编写使用的,所以就很值得我们深究。
分类:自定制协议 、知名协议

自定制协议

自定制协议是我们程序员自己约定的数据格式
当程序员自定制一个协议的时候,需要考虑的三个因素是:
可阅读性:当我们组织数据的时候,如果使用字符串进行组织,当我们抓个包,就能看到信息,排查错误就很简单。可阅读性提高了。
解析性能:但只考虑可读性是不行的,组织数据时,经过层层加密,接收数据时也要进行层层解析,如果操作不好,就会加大解析成本。但数据做的简单,就会不安全,所以需要程序员在自定制协议时,把握好这三个因素。
传输新能:举个简单的例子,如果要传输1和2两个数字,如果将他们组织成字符传输,只需要传输2个字节,但要是传输两个整形数字,就要传输8个字节,字节数多了,数据就多了,性能就下降了。但要是传输一个很大的整型数字,1231245328543985,这么大的数字也只占4个字节,如果传输字符串就很多了,这也是程序员需要考虑的问题。
示例:
一个网络版的迷你计算器,客户端将两个数字和运算符发给服务端,服务端返回结果
int num1 = 11;int num2 = 22;char op = ‘+’;
在网络通信中,如何将这些数据发送给客户端呢?

使用结构体约定数据格式
	typedef struct{int num1 = 11,int num2 = 22,char op = '+'}tmp_t;
	tmp_t tmp;
	解析时就可以使用tmp.num1这种方式访问结构体的成员变量,直接取出对应字节的数据。

代码:

在这里插入代码片

序列化与反序列化:
传输数据时,为了确保安全,当然不能之间传输易读的数据,而是将数据进行序列化,接收数据时进行反序列化。
序列化:将多个数据对象,按照指定的协议组织,进行持久化存储或者网络传输的二进制数据传输;可以理解为就是组织数据。
反序列化:将一个二进制数据串按照指定协议解析得到各个数据对象。
几个典型的序列化方式:
json序列化
protobuf序列化

知名协议之HTTP协议解析

HTTP协议——超文本传输协议
传输 超文本数据:xml、html等
解析HTTP:
http协议的数据结构、http的协议格式

URL

例:在这里插入图片描述

URL:统一资源定位符(Uniform resource locator)
	简称/俗称:网址
	理解:定位网络中某一台主机的某个资源
	   http  ://   usr:passwd  @     ip:port       /path    ?   key=val&key&val                #ch
	协议方案名称      用户名密码 	      域名端口信息  要请求的资源路径   query_string(由键值对组成) 片段标识符
	域名:
	http://usr:passwd@ip:port/path?key=val&key=val#ch

域名
https://gentle-wu:wjy2851518…@gitee.com/gentle-wu/linux-warehouse
用户名和密码也可以没有
gitee.com就是一个域名,在网址上我们允许输入一个公司的特有域名来访问这个公司的网站,但实际上会在内层将这个域名转换为ip地址进行访问。原因就是ip是一个点分十进制,不容易辨别,而一个域名就可以很容易识别。
我们也可以使用ip代替域名,比如打开百度我们可以输入www.baidu.com,但我们也可以用ping看一下百度的ip,
在这里插入图片描述
然后输入ip访问网站,就可以转到百度了。
在这里插入图片描述
所以我们既可以通过ip访问网址,也可以通过域名来访问。
端口:
域名/ip可以定位网络中某一台主机的位置,而我们通信时,一般是访问某个服务的某个进程,根据理解,端口信息必不可少
HTTP协议默认使用80端口,不需要我们指定,浏览器会自己加上
如果需要指定一个特定的端口,就可以在ip的后面加上冒号+端口号在这里插入图片描述
拓展:https默认使用443端口,ftp使用21端口,ssh使用22端口
路径:
通信时,我们一般要访问一台主机的某个进程,那在这个进程中我们需要什么呢?
当然是请求资源了,怎么请求到我们想要的资源?
每一台主机上都有自己的空间,空间中存放着资源,通过路径可以标识一个资源的位置。
显然,加上资源路径,就可以访问到我们想要的数据了。
格式:/path 需要理解,这个/并不是根目录,而是指定的一个相对目录,浏览器会校验目录是否合法,服务器也会对这个相对目录进行校验,看它到底是不是我这台主机下的目录。
query_string:
查询字符串,提交给服务器的数据,由一个个键值对组成,键值对之间由&间隔,数据中不能出现特殊字符。
为什么不能出现特殊字符?
如果我给url中写入的字符串中由&符,是不是就会和间隔符号产生二义?
所以若要由特殊字符,就必须进行url编码,将字符进行转义,避免产生歧义。

urlencode:编码 - 将特殊字符的每个字节转换为16进制数字的字符,并且使用%进行转义标识  + -> %2b
				如果单单转成16进制字符,还是会产生二义。比如如果提交的数据既有‘+’又有‘2b’字符,就会产生二义,
				这时就需要再进行间隔,使用前缀%表示这几个字符是转义后的字符(‘+’的16进制是2b)
urldecode: 解码 - 在查询字符中遇到%,则将紧随其后的两个字符转为16进制数字,第一个数字乘以16或者左移4位加上第二个数字

片段标识符:
格式:#ch
描述了某一个资源的某一个片段,可以跳转到某一个页面的某一个位置。

--------------------------------------------------------我是间隔符-----------------------------------------------------------
--------------------------------------------------------我是间隔符-----------------------------------------------------------
--------------------------------------------------------我是间隔符-----------------------------------------------------------

HTTP协议格式

要点:
http协议是明文协议,在传输层使用TCP协议
http是明文字符串传输协议
https只是对http字符串进行了加密
http协议是一个简单的请求-响应协议
格式:
将http通信协议划分为四个部分理解:
首行:请求首行、响应首行
头部:请求头部、响应头部
空行:一个\r\n
正文:请求正文、响应正文
每个部分以\r\n间隔

fiddler抓包抓一个http传输看一下格式

在这里插入图片描述

请求:

首行:
 	GET /index.html HTTP/1.1
	请求行: 请求方法、URI、协议版本

理解URI:

	URI是统一资源标识符,URL是统一资源定位符
	实际传输中请求头部中URI并不包含协议方案名称、域名端口信息等,只包含资源路径和查询字符串和片段标识符,但上面例子中包含http://……是因为这是fiddler抓包抓到的信息,如果使用wrieshark是不会有的

理解请求方法:

请求方法:GET  HEAD  POST (PUT、DELETE、OPTIONS、CONNECT、LINK、UNLINK)
		GET:主要用于请求实体资源,也可以提交数据,但是要在URL中提交,但是URL有长度限制,且安全隐患高。
		URL的长度限制:在标准文档中,URL并没有长度的限制,只是由各个服务厂商定义一个URL有多长,早期大概1kb,现在大概3~4kb
		HEAD:功能与GET类似,但是请求中没有实体
		POST:主要用于提交客户端表单数据,数据在正文中
		表单数据:正文中form括起来的数据,一般都有账户信息、密码信息、是否记住密码信息等,提交表单数据进行处理。

当我们使用百度查询一个东西的时候,我们就是在使用GET请求方法,这个时候我们也将要查询的数据提交给服务器了,只不过放在了URL的查询字符串中。
当我们点击一个网站,获得登录界面时,也是使用GET请求方法,这时并没有提交数据,但输入用户名密码,提交之后,就是使用POST请求方法提交表单数据,数据放在正文中。
理解协议版本:

HTTP/0.9:这时候的http仅用于传输html数据,并且只有GET请求方法,协议格式不完整。
		短链接:http传输建立在tcp上,短链接发送一个请求,得到相应之后,关闭连接。再发送请求,建立连接,关闭连接。
HTTP/1.0:正式规定了http协议格式,增加了多种请求方法,有了基础的缓存控制
		短链接:http传输建立在tcp上,短链接发送一个请求,得到相应之后,再发送数据,响应之后,再发送数据,不通信了就关闭连接
HTTP/1.1:在1.0的基础上增加了更多的请求方法和头部描述信息,支持了长连接管线化运输
	长连接:长连接一次连接可以发送多条请求,但响应顺序必须和请求顺序相同
	管线化传输方式:提高信道的利用率
HTTP/2.0(还没有使用,修正中):之前的版本都是采用明文传输,暴露性大,不安全。2.0采用二进制流传输,并且进进行多路复用,允许服务端主动推送数据。

在这里插入图片描述
请求头部:

描述本次请求的关键字段信息,由key:val形式的键值对组成,并且每个键值对以 \r\n 间隔
Connection : 控制长短连接  keep-alive 长连接    close 短连接
Cache-Control : 缓存控制      max-age = 0 表示每次都要重新请求
User-Agent : 客户端的属性信息
Accept : 描述自己所能接受的数据属性
Content-Type : 描述正文数据类型******特别重要,决定了正文该如何处理
		浏览器收到这个类型,会按照这个类型来响应,比如html渲染操作,收到渲染类型才会渲染界面,如果是一个html下载类型,服务器收到之后就可能会下载一个html文件。
Content-Length:用于描述正文数据长度*****特别重要
		服务器接收数据时,从首行接收到空行,将头部接受完成之后对头部进行解析,解析正文需要接受多少长度的数据,如果长度出问题,就会出现一连串问题,典型的例子就是tcp中的粘包问题。
		Content-Length就可以解决粘包问题
Referer: 请求头包含了当前请求页面的来源页面的地址,即表示当前页面是通过此来源页面里的链接进入的。根据这个就可以跳转回去。

Cookie :可以带有一些信息(多是认证信息),持续在通信中描述
		客户端每次从cookie 文件中读取数据通过cookie文件向服务端传递信息,维护客户端状态信息
说明:
	早期http是短连接通信,是一个无状态协议,不会保存客户端状态,每次访问都要进行登录,于是http就引入了cookie保持客户端的状态信息
	但如果cookie在通信中被劫持,就会导致认证信息泄露,那怎么办?
	在通信中引入session

空行:

间隔头部与正文
就是一个 \r\n,与上面头部的最后一行的\r\n组成\r\n\r\n作为头部结尾
上面的请求头部每一个键值对都以\r\n间隔,所以接收http数据的时候,当连续接收到两个\r\n时,系统就知道这是一个空行了,认为头部到此结束。
先获取完整头部,然后根据头部中的Content-Length获取正文长度,然后获取指定长度的正文,通过这种方式获取完整的一条http请求数据。

正文:

提交给服务端的数据

响应:

例:
在这里插入图片描述

首行:

HTTP/1.1 303 See other
包含三个要素:
协议版本:0.9、1.0、1.1、2.0
响应状态码:标识本次请求服务端所作出的响应结果	
	1xx:描述信息
	2xx:标识本次请求正确处理完毕    
			典型:200  OK请求处理成功
	3xx:重定向 - 你请求的资源在另一个位置,要求客户端重新请求新的位置
			典型:301 - 永久重定向 - 如果永久重定向了,下次访问这个资源时,就不会访问原来的地址,会直接访问重定向之后的地址。
			比如我现在访问192.168.2.2,服务器返回给我301,说明这个网页永久重定向了,假设重定向到192.168.2.3了,如果我现在不关闭2.2,再打开一个浏览器访问2.2,这时浏览器会自己访问到2.3.
				 302 - 临时重定向 - 如果是临时重定向,访问时还是访问原链接,并不访问新连接
				 303 - 查看其他地址。图例中就是303 See Other ,当我们登录一个页面,会跳转到自己用户下的已登陆的另一个界面。
	4xx:客户端请求错误
			典型:400 - 请求错误(Bad Request)
				 404 - 表示请求的资源不存在(Not Found) - 常用于敏感事件
	5xx:表示错误服务端
			典型:500 - 表示服务器不支持请求的功能
				 502 - 代理请求失败/收到无效响应
				 504 - 代理请求超时 
	具体查询网址:https://www.runoob.com/http/http-status-codes.html
状态码描述:对状态码的描述信息,可以是官方文档描述,也可以是自定义描述

头部:

关于本次响应的一些关键字段描述信息,以key:val键值对组成,以\r\n间隔
典型信息:
	Server:服务器版本信息
	Date:本次请求时间
	Content-Type描述本次响应的正文是什么样的数据,数据类型,编码格式
	Transfer-Encoding:传输方式,表示相应的数据是如何传输的
		chunked - 分块传输方式
			将正文分为多块传输,用于正文长度未知的情况
			在正文每行之前加上 xx\r\n,xx表示本行长度,为16进制数。
			如:
				0e\r\n
				<!DOCTYPE html>
				06\r\n
				<html>
				0\r\n\r\n
				
				每发送一块数据之前,先发送这块数据有多长。
	Expires:数据过期时间
	Location:重定向的新链接位置
	Set-Cookie:服务端通过Set-Cookie向客户端传递信息,传递的信息会被保存在客户端浏览器的cookie文件中

Cookie、Setcookie和session

http0.9、1.0的短链接弊端显而易见,解决方法就是长连接。那如何实现长连接呢?
http的长连接状态就是由Cookie维持的,Cookie维持服务端的状态信息。
这个过程是怎样的呢?(短链接弊端)
当客户端第一次向服务端发送登录请求时,账号密码就是cookie信息,服务端会记录这些信息,通过Set-Cookie返回给客户端,客户端收到服务端响应的这些信息后,将其保存到cookie文件中,等下次请求这个服务器时,就会自动从这个cookie文件中读取Cookie信息,填充到请求头部Cookie中,发送到服务端。
问题是:
cookie中包含了大量的客户端隐私信息,存在安全隐患。
怎么解决?
引入session:解决安全隐患。
客户端登录服务器成功之后,服务端创建session会话保存cookie隐私信息,返回一个会话id,通过Set-Cookie将会话ID返回给客户端,客户端收到会话ID之后保存在cookie文件中,等下次访问将会话ID作为头部cookie信息发给服务端,服务端解析头部之后,就可以通过会话ID在会话ID表中找到对应的会话信息,就可以维持状态了。

HTTPS协议

https是http的加密协议,并不是一个新的协议。
http的加密:ssl加密
解释:https是以安全为目标的http通道,在http进行传输加密身份验证确保数据传输过程的安全性,这个过程就是ssl加密。
身份验证
流程:找一个通信双方都信任的第三方权威机构,给双发办法证书,通信前先将证书发送给对方
对方拿到证书之后进行解析得到相关信息(颁发者、颁发给…)

  • 1.确认当前通信机构是否是自己想要通信的机构
  • 2.确认当前通信机构是否是自己信任的机构
  • 3.在这个自己信任的机构中进行确认(确保证书有效不是假证)

身份验证成功之后,依然存在数据泄密的隐患,这就需要进行传输加密。

传输加密
概念:对通信数据进行加密处理防止网络监听
对称加密:加密与解密算法(密钥)相同

通信双方进行协商,协商出一种数据的加密解密方式。
缺陷:对称密钥容易被劫持;如果在协商过程中就被劫持了密钥就没了
有点:加解密效率较高,通信效率高;

非对称加密:加密解密算法(密钥)不同

通过特定算法(RSA)生成一对密钥:公钥和私钥
通信前将公钥发送给通信双方,发送端使用公钥对数据进行加密,接收方使用私钥对数据进行解密。
这样一来,就算通信被监听,私钥始终是掌握在通信双方手里的,监听只能监听到公钥,并没有什么用。
优点:安全,不怕被监听
缺点:加解密效率低导致通信效率低

混合加密:先使用非对称加密保护一个对称加密的协商过程,对称加密协商完成之后,使用对称加密进行传输加密
第一次服务器给对端一个公钥,对端传回来一个随机数和自己支持的对称算法列表,服务端收到之后再将自己支持的算法列表和一个随机数发给对端,
这两次通信之后,双方都知道对方支持的对称算法列表和对方的随机数,根据这两个信息计算出一个对称密钥,在非对称密钥的保护下双方就可以使用对称密钥进行通信。
在这里插入图片描述
SLL加密总结:
上面知道,https就是在http的基础上进行身份验证和数据加密,这个过程就是:
一个需要被验证身份的机构,生成一对密钥(公钥和私钥),然后去权威机构生成一个CA证书(并将公钥和自己支持的对称算法列表交给权威机构),生成的证书中具有机构的信息和密钥的信息,通信之前,只需要将证书交给对方完成身份验证,双发也可以从证书中获取到对方支持的对称通信列表,协商一个对称密钥,进行对称传输,即可完成https传输。
在这里插入图片描述
拓展内容:RSA非对称加密算法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值