网络原理 -- HTTP
目录
应用层
自定义协议
数据组织格式总结
HTTP
抓包工具
HTTP协议格式
HTTP请求报文
HTTP响应报文
HTTP请求(Request)
认识URL
URL中的可省略部分
URL encode
认识"方法"(method)
GET方法
POST方法
上节回顾
TCP 编程注意事项:
1. 读写数据通过 Socket 内置的 InputStream 和 OutputStream,读写基本单位是字节
2. 在编写客户端服务器的时候,需要约定请求/响应之间的分隔符(\n),约定好从哪到哪是一个完整的请求/响应
3. 服务器这边 accept 得到的 socket 对象,需要及时关闭
4. 要处理多个客户端,需要搭配多线程/线程池、
如果客户端进一步增加,此时多线程/线程池就会产生出大量的线程。操作系统中内置的IO多路复用可以解决这个问题,它本质上是一个线程同时负责处理多个客户端的请求
一个线程同时负责处理多个客户端的请求:
每个客户端绝大部分时间是沉默的(多个客户端同时发数据的概率比较小),工作线程只需要等待,等到客户端发来数据的时候,线程再来处理就可以了
应用层
和应用程序直接相关。程序员写的代码,只要是涉及到网络通信的,都可以视为是应用层的一部分
应用层中涉及到的网络通信协议,很多也都是程序员自定制的
具体如何自定义协议呢?
自定义协议
分成两个阶段:
1. 根据需求,明确传输哪些信息
例如,外卖平台的客户端-服务器
客户端打开外卖平台后:
请求:用户的位置信息(经纬度),用户的 id
响应:商家的id,商家的名字,商家的图片,评分,配送费,种类(若干条)
2. 约定好信息组织的格式
1)行文本的方式
请求:
响应:
2)通过 xml 格式来约定请求和响应的数据
xml 和 html 一样,都是成对的标签构成的键值对结构,不同的是,html 标签内容都是固定的(后来的 html 5允许自定义标签了),xml 标签内容是自定义的
请求:
响应:
优点:可读性好
缺点:冗余信息太多,网络传输会消耗更多的带宽
3)json
当下最流行的网络数据格式组织的方案
请求:
优点:可读性也是很好的,消耗的带宽也比 xml 更节省
缺点:还是存在冗余信息
4) protobuf
基于二进制的格式,约定一段二进制数据,哪几个字节表示哪个信息,对数据进行压缩,不涉及到 json/xml 冗余信息了
优缺点:带宽消耗最少,可读性变差了
适用性能要求高的场景,如果性能要求不高,还是更建议使用 json
数据组织格式总结
1. 行文本(最原始)
2. xml(比较原始,可读性好,冗余较多)
3. json(主流的方式,可读性好,冗余一般)
4. protobuf(高性能场景下使用的方式,可读性差,冗余最小)
HTTP
HTTP(全称为"超文本传输协议") 是应用层协议,是一问一答模式的协议。客户端发一个请求,服务器就返回一个响应,请求和响应一一对应
网络通信中也有其他的模型
多问一答:上传大文件
一问多答:下载大文件
多问多答:远程控制(todesk)
浏览器打开网页的场景/手机 app 加载数据的场景典型的一问一答场景,使用 HTTP 非常合适
抓包工具
1. 抓包工具是一个软件,相当于 “代理”,能够获取到网络的数据包,详细的格式都可以解析出来。
2. 电脑上所有的网络通信,都会先发给这个抓包程序,抓包程序再把数据转发给服务器
3. 梯子本质上也是代理,可能会和抓包工具冲突。使用抓包的时候,一定要关闭梯子/梯子类的浏览器插件
正向代理:代表客户端干活
反向代理:代表服务器干活
wireshark:知名的抓包工具
可以抓很多协议,如 HTTP,TCP,UDP,IP 等,以太网数据帧,但使用门槛较高,比较麻烦
fiddler:专门抓 http 的
功能更简单(也足够用),使用更简单
简单设置一下,支持 https
首次勾选会弹出一个对话框,提示你是否要信任人家的根证书,一定要选择 yes,没点yes,只能卸载重装了
使用:
在百度上搜索,抓包工具抓到的列表,只关注关键的请求(body较大,图中是135443)
双击看到详细情况
左侧窗口,是抓到的当前的请求/响应的列表(fidder只抓http),右上是请求,右下是响应
说明:
1. 侧窗口显示了所有的 HTTP 请求/响应,可以选中某个请求查看详情
2. 右侧上方显示了HTTP请求的报文内容(切换到Raw标签页可以看到详细的数据格式)
3. 右侧下方显示了HTTP响应的报文内容(切换到Raw标签页可以看到详细的数据格式)
4. 请求和响应的详细数据,可以通过右下角的 view in Notepad 通过记事本打开
5. 可以使用ctrl+ a全选左侧的抓包结果,delete键清除所有被选中的结果
为了节省网络带宽,响应数据通常是压缩后传输的。点击下图黄色按钮可以解压缩
抓包列表颜色:
红色 表示报错
蓝色 表示这个请求得到了个网页
绿色 表示得到了一个 js
灰色 表示这个响应的数据已经被缓存了
HTTP协议格式
HTTP请求报文
HTTP 请求报文由四部分组成:
1、请求行(首行),包含三部分:
- 请求方法:描述需求的目的
- URL:描述要访问的网络资源的具体位置
- 版本号:表示 HTTP 的版本
2、请求头(header):其中包含了很多行,每一行都是一个键值对,键和值之间使用冒号和空格来进行分割,并且键值对的个数也是不固定的,不同的键和值表示的含义也是不同的
3、空行:相当于请求头的结束标记,用来标识 header 结束了,类似于链表中的null
4、请求正文(body):空行后面的内容都是 Body,Body 允许为空字符串。如果 Body 存在,则在Header 中会有一个 Content-Length 属性来标识 Body 的长度
示例:
HTTP响应报文
HTTP 响应报文也是由四部分组成:
1、首行:包含了三个部分:版本号、状态码以及对状态码的描述
2、响应头(header):也是键值对结构,每个键值对独占一行,每个键和值之间使用冒号和空格进行分割,不同的键值对表示不同的含义
3、空行:表示响应头的结束标记,标识 header 部分结束
4、响应正文(body):空行后面的内容都是 Body,Body 允许为空字符串.如果 Body 存在,则在Header 中会有一个 Content-Length 属性来标识Body的长度;如果服务器返回了一个 html 页面,那么 html 页面内容就是在 body 中
示例:
HTTP请求(Request)
认识URL
平时俗称的 "网址",其实就是 URL(Uniform Resource Locator 统一资源定位符)
一个具体的URL:
协议名://ip地址(域名):端口号/路径?查询字符串
https://blog.csdn.net//personInf/student?userId=10000&classId=100
在这个URL中有些信息被省略了
https:协议方案名。常见的有 http 和 https,也有其他的类型(例如访问mysql时用的jdbc:mysql)
user:pass:登陆信息。现在的网站进行身份认证一般不再通过URL进行了,一般都会省略
blog.csdn.net:服务器地址.此处是一个"域名",域名会通过DNS系统解析成一个具体的IP地址 (通过ping命令可以看到,blog.csdn.net 的真实IP地址为 111.6.187.160)
使用 ping 命令查看域名对应的IP 地址
1. 在开始菜单中输入cmd,打开命令提示符
2. 在cmd中输入 ping blog.csdn.net,即可看到域名解析的结果
端口号:上面的URL中端口号被省略了。当端口号省略的时候,浏览器会根据协议类型自动决定使用哪个端口。例如http协议默认使用80端口,https 协议默认使用443端口
/personInf/student:带层次的文件路径
userId=10000&classId=100:查询字符串(query string)。本质是一个键值对结构,键值对之间使用&分隔,键和值之间使用=分隔
片段标识:此URL中省略了片段标识。片段标识主要用于页面内跳转 (例如Vue官方文档:https://cn.vuejs.org/v2/guide/#%E8%B5%B7%E6%AD%A5,通过不同的片段标识跳转到文档的不同章节)
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格式
"+" 被转义成了 "%2B" :
urldecode 就是 urlencode 的逆过程
认识"方法"(method)
GET 和 POST 是最常见的请求
获取html,获取css,获取js等操作,都是get;登录,上传文件等操作,都是post
GET方法
GET请求的特点:
- 首行的第一部分为GET
- URL的query string可以为空,也可以不为空.
- header部分有若干个键值对结构.
- body部分一般为空,如果需要通过GET给服务器发送一些数据,是通过query string 传递过去的
小知识:
F5 刷新,重新访问服务器
ctrl+F5 强制刷新,忽略本地缓存,所有资源都重新从服务器获取
浏览器的缓存机制:
通常情况下,从网络加载数据比从硬盘加载要慢,浏览器为了加快访问页面的速度,就会把页面依赖的一些静态资源(css,js,图片,字体,mp3...)这些内容缓存到硬盘上,第一次访问服务器,需要加载这些,后续再访问,就不必重新加载。
所以按 ctrl+F5 强制刷新,用 fiddler 可以抓到更多
POST方法
两个典型的场景
1. 提交用户输入的数据给服务器(例如登陆页面)
2.上传:请求是带有正文的,正文保存了当前上传的数据的内容
POST请求的特点
- 首行的第一部分为POST
- URL的querystring一般为空(也可以不为空)
- header部分有若干个键值对结构
- body部分一般不为空;body内的数据格式通过header中的 Content-Type指定;body的长度由header中的 Content-Length 指定
GET和POST的区别:
GET和POST没有本质区别,经常是能够混用的。从使用方法习惯上来说,主要是两个方面的区别:
1. 语义上的区别
GET 表示从服务器获取数据,POST 表示往服务器提交数据
2. 携带数据的方式
GET 经常把数据放到 url 的 query string 中,POST经常把数据放到body 中(POST 也可以带有 query string,GET 理论上也可以带 body(少见))
除了上面两种主要区别,还有其他区别:(了解)
3. GET请求通常建议设计成幂等的(是HTTP标准文档给的建议,但是只是建议,不是强制要求),POST无要求
幂等:指多次相同请求产生相同结果且不改变资源状态
4. GET 设计成幂等了,就可以允许GET 请求的结果被缓存;POST 由于不要求幂等,经常是不幂等的,就认为是不能被缓存的
一些错误的说法:
1. POST比GET更安全
在登录场景,输入用户名和密码,如果是GET请求,用户名密码就会放到 url 的query string中,会显示在浏览器地址栏上,所以会有这个说法。
保证安全,关键是 “加密传输",POST 传输如果不加密,随便抓个包也看到用户密码。只要明文传输,都谈不上安全
2. GET传输数据有长度限制
早期 IE 浏览器的年代(IE6,windows xp),对URL的长度是有限制的。这个时期传输的数据太多,可能就会被截断,现在的主流浏览器/服务器早都没有这样的限制了
3. GET只能传输文本,POST可以传输二进制
GET 确实 url 只能放文本,但可以把二进制通过 base64 转码成文本再进行传输
PUT 和 DELETE
主要用在实现 Restful 风格的 api
Restful 风格是设计服务器接口的一种 “习惯",增删改查使用不同的方法
新增:POST
删除:DELETE
修改:PUT
查询:GET