(一)理解应用层协议
我们之前说过我们网络分为五层分别是:应用层.传输层.网络层.数据链路层.物理层,对于我们现在来说,最常接触的就是应用层和传输层了,之前我们讲述了传输层的TCP和UDP协议,那现在我们就来讲一下应用层协议
我们来简单理解下应用层协议,如果我们把tcp/iP五层模型比作送快递,那么传输层解决的就是快递的发货方和收货方,而两端需要对数据进行加工处理或者使用,所以我们应用层协议就诞生了,不关心如何发送,发送给谁,只关注应用细节。
我们可以自定义一个应用层协议,但是我们也要确保接收方同样使用这个自定义协议,所以在互联网发展这么久,有许多经典的应用层协议流传下来,HTTP就是其中之一。
我们来了解一下HTTP的工作流程,实际上就是一问一答,我们给服务器发送一个HTTP请求,服务器就回经过处理,返回一个HTTP响应
实际上,我们访问一个网站,可能会涉及多次的HTTP请求和响应。
(二)HTTP的协议格式
我们怎样看到HTTP的请求和响应呢?这时候我们可以利用一些抓包工具
Fiddler
我们一进入fiddler他会让你先安装一个证书,一定要点yes,至于为什么我们会在下一篇博客,HTTPS中说明
上述就是我们一进入fiddler的界面,一进入就会自动开始抓包,到我截图成功,已经抓了这么多了,那么接下来我们就来看看该怎么使用fiddler
如何使用fiddler
• 左侧窗⼝显⽰了所有的HTTP请求/响应,可以选中某个请求查看详情.
• 右侧上⽅显⽰了HTTP请求的报⽂内容.(切换到Raw标签⻚可以看到详细的数据格式)
• 右侧下⽅显⽰了HTTP响应的报⽂内容.(切换到Raw标签⻚可以看到详细的数据格式)
• 请求和响应的详细数据,可以通过右下⻆View in Notepad 通过记事本打开.
fiddler抓包的原理
fiddler相当于一个代理(我们平常使用的加速器和“翻墙软件”也都是代理)
浏览器在访问网站时,会将HTTP请求先发送给fiddler,再由fiddler将请求转发给对应的服务器,服务器返回响应时,也会将响应传给fiddler,再由fiddler传回给浏览器。
由以上操作,fiddler就可以很好的把两者间的交互信息展现出来
抓包结果展示
我们来展示下fiddler给我们抓到的HTTP请求和响应的数据包
HTTP请求
1.首行:包括方法,url和版本号
2.Header:请求的属性,和一些键值对,每组都用\n来隔开
3.空行:遇到空行就表示Header结束了
4.body:空行后的内容都是body,用来传输数据
HTTP响应
1.首行:协议版本号,状态码,状态码解释
2.Header:请求的属性,一些键值对,每组用\n来表示
3.空行:遇到空行表示 Header结束
4.body:空行后的内容都是body,用来传输数据
那么上述我们发现HTTP请求和响应中有一个东西很奇怪,这个空行除了表示Header结束外,还有没有其他作用?
这个空行不仅可以当作是Header的结束标志,也可以防止粘包问题,对,就是我们之前说到的,TCP由于是面向字节流的所以会有粘包问题,而HTTP在传输层依赖HTTP协议,所以也会有粘包问题。
HTTP请求中的信息
URL
平时我们说的网址,也就是url,我们常说www. .com就是url中的服务器地址
那我们现在来逐步拆分一下
1.http:协议方案名,常见的有http和https
2.user:pass:登录信息,之前用来保存我们的身份认证信息,但是现在我们一般使用cookie,现在一般都会省略
3.www.example.jp:此处是一个域名,域名会通过DNS系统解析成一个具体的ip地址
4.80:端口号,表示我们要访问对应ip的哪一个端口,此处这个端口可以省略,如果省略,我们浏览器会根据协议来使用默认的端口,比如http默认就是80,而https就是443
5.带层次的文件路径
6.uid=1:查询字符串,本质是一个键值对结构,键值对之间用&来分割,键和值使用=分隔
7.#ch1:片段表示,主要用于页面内的跳转
url中有一些可以省略,在上面我们说端口是可以省略的,除了端口如果协议名省略,那么我们默认为http//: 如果带层次文件路径省略,那就相当于/.,有些服务器会自动访问/index.html,查询字符串和片段标识符也都可以省略
我们再来说一下查询字符串,查询字符串中的内容都是键值对结构的,其中key和va;ue的取值和个数都是我们自己约定的,我们可以在这里传输信息给服务器,但是我们不可以写中文,这就涉及到我们的URL encode
关于URLencode
像/?的一些字符,在url中会被当做特殊意义进行理解,就跟我们学c是语言时的/n类似,所以这些字符是不可以随便出现,如果我们一定要带有这些特殊字符,就需要对这些字符进行转义
⼀个中⽂字符由UTF-8或者GBK这样的编码⽅式构成,虽然在URL中没有特殊含义,但是仍然需要进 ⾏转义.否则浏览器可能把UTF-8/GBK编码中的某个字节当做URL中的特殊符号.
转义的规则是:将需要转码的字符转为16进制,然后从右到左取四位不足四位,直接进行处理,每两位变成一位,前面加%,变成%xy的格式即可
+被转义成了"%2B"
解码就是urldecode,与urlencode的方式正好相反
方法
我们这里主要讲两个方法,GET和POST
1.GET
GET是我们最常用的方法,一般用来获取数据
这就是一个GET请求
GET请求有以下几个特点:
1.首行部分会标识为GET
2.url的查询字符串可以为空也可以不为空
3.header中有若干键值对
4.body部分为空
2.POST
POST⽅法也是⼀种常⻅的⽅法.多⽤于提交⽤⼾输⼊的数据给服务器(例如登陆⻚⾯).通过HTML中的form标签可以构造POST请求,或者使⽤JavaScript的ajax也可以构造POST请求.
POST请求的一些特点
1.首行方法为POST
2.url中的查询字符串一般为空,因为我们一般使用body传数据,也可以不为空
3.header部分有若干键值对结构
4.body部分一般不为空,用来传输数据,且内容格式由header中的Content-Type来指定,内容长度由header中的Content-Length来指定
3.GET和POST的一些区别
• 语义不同:GET⼀般⽤于获取数据,POST⼀般⽤于提交数据.
• GET的body⼀般为空,需要传递的数据通过querystring传递,POST的querystring⼀般为空,需 要传递的数据通过body传递
• GET请求⼀般是幂等的,POST请求⼀般是不幂等的.(如果多次请求得到的结果⼀样,就视为请求是 幂等的).
• GET可以被缓存,POST不能被缓存.(这⼀点也是承接幂等性).
Header
我们来认识一下Header
Header的格式也是键值对结构,每个键值对占一行,键值之间用冒号分隔
1.HOST
表示服务器注意的地址和端口
2.Content-Length
表示body中的数据长度
3.Content-Type
表示body中数据的格式
4.User-Agent(UA)
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)
内含有操作系统信息和浏览器信息,之所以有UA是因为不同的操作系统和浏览器支持的页面是不一样的
5.Refer
表示这个页面是从那个页面跳转过来的,很多页面广告结算工钱,就是根据这个,但是有一些人会专门去劫持HTTP请求,并且进行修改,这就会导致工钱结算的不对,也就诞生了我们后面HTTPS
6.Cookie
Cookie中存储了⼀个字符串,这个数据可能是客⼾端(⽹⻚)⾃⾏通过JS写⼊的,也可能来⾃于服务器 (服务器在HTTP响应的header中通过Set-Cookie字段给浏览器返回数据)
而Cookie就能实现身份标识的用处
跟会员卡类似,在第一次去饭店时,如果你办会员卡,老板会在他的电脑上录入你的信息,并且会给你一张卡,你下一次去吃饭,只要刷卡就会显示出你的信息,各个饭店的会员卡可以同时拥有,也就是说我们可以同时拥有多个Cookie
Body
正⽂中的内容格式和header中的Content-Type密切相关.下⾯也罗列了三种常⻅的情况.
1)application/x-www-form-urlencoded
2)multipart/form-data
3)application/json
状态码
200 OK
一般来说我们见到的大部分都是这个状态码,表示访问成功
404 Not Found
找不到对应资源,我们在输入一个url之后,访问对应服务器上的一个资源,如果没有你寻找的资源,就会给我们返回404
403 Forbidden
表示访问被拒绝,通常是因为我们访问了一些需要特定权限才能进入的页面,如果我们没有登录或者权限不够,就会返回403
405 Method Not Allowed
表示我们传输的方法错误,有可能服务器只接受get方法,而你传输了一个POST方法
500 Internal Server Error
一般是服务器崩溃了,会给我们发送这个状态码
504 Gataway TIMEout
表示服务器返回响应超时,可能是服务器崩了也可能是服务器的负载比较大
302 Move temporarily
临时重定向:我们在登录一个页面时,如果自动跳转了就会给我们返回一个302的状态码
301Moved Permanently
永久重定向:当浏览器收到这个响应时,后续我们会把这个地址更改成新的地址
(三)如何构造HTTP请求
我们可以利用postman来构造请求,或者我们可以通过form表单或者ajax,Java socket来构造请求,这里我们会在javaee中说明