9.4 应用层协议
应用层是TCP/IP模型的最上层,直接为应用程序提供网络服务,我们日常开发接触最多的就是应用层协议。应用层协议定义了应用程序之间通信的规则和报文格式。
HTTP协议(超文本传输协议)
HTTP是互联网上使用最广泛的应用层协议,是Web的基础,所有的网站、Web服务都基于HTTP协议。
HTTP的特点
- 客户端-服务器模型:客户端发起请求,服务器响应请求
- 无状态:HTTP协议本身不保存客户端的状态,每个请求都是独立的,服务器不知道多个请求是否来自同一个客户端,需要通过Cookie、Session、Token等机制来维护状态
- 简单灵活:请求和响应结构简单,支持各种数据类型(文本、图片、音视频等)
- 明文传输:HTTP本身是明文传输的,内容容易被窃听和篡改,所以现在通常使用HTTPS加密传输
HTTP请求结构
一个HTTP请求由三部分组成:请求行、请求头、请求体:
GET /index.html HTTP/1.1 # 请求行:方法 路径 HTTP版本
Host: www.example.com # 请求头
User-Agent: Mozilla/5.0
Accept: text/html
Connection: keep-alive
# 空行分隔头和体
username=test&password=123456 # 请求体(GET请求通常没有请求体)
请求方法
HTTP/1.1定义了八种请求方法:
- GET:获取资源,请求参数通常放在URL中,请求体为空,幂等
- POST:提交数据,通常用于创建资源,请求体包含提交的数据,非幂等
- PUT:更新资源,替换整个资源,幂等
- DELETE:删除资源,幂等
- HEAD:和GET类似,但只返回响应头,不返回响应体,用来获取资源元信息
- OPTIONS:查询服务器支持的请求方法和跨域权限
- PATCH:部分更新资源,非幂等
- CONNECT:建立隧道连接,用于HTTPS代理
- TRACE:回显请求,用于调试
常见请求头
- Host:请求的主机名和端口
- User-Agent:客户端标识,浏览器、操作系统等信息
- Accept:客户端能接收的内容类型
- Content-Type:请求体的类型,常见的有:
- application/x-www-form-urlencoded:普通表单提交
- multipart/form-data:文件上传
- application/json:JSON格式数据
- Content-Length:请求体的长度
- Cookie:客户端保存的Cookie信息
- Authorization:认证信息,通常是Bearer Token等
- Referer:请求来源页面
- Cache-Control:缓存控制
HTTP响应结构
HTTP响应也由三部分组成:状态行、响应头、响应体:
HTTP/1.1 200 OK # 状态行:版本 状态码 状态描述
Server: nginx # 响应头
Content-Type: text/html; charset=utf-8
Content-Length: 1024
Cache-Control: max-age=3600
<!DOCTYPE html> # 响应体
<html>
...
</html>
状态码
状态码表示请求的处理结果,分为五类:
- 1xx:信息性状态码,表示请求已接收,继续处理
- 100 Continue:继续发送请求的剩余部分
- 101 Switching Protocols:切换协议,比如切换到WebSocket
- 2xx:成功状态码,表示请求已成功处理
- 200 OK:请求成功
- 201 Created:资源创建成功
- 204 No Content:请求成功,没有响应体
- 206 Partial Content:部分内容,用于断点续传
- 3xx:重定向状态码,表示需要进一步操作才能完成请求
- 301 Moved Permanently:永久重定向,资源已经永久移动到新地址
- 302 Found:临时重定向,资源临时移动
- 304 Not Modified:资源未修改,可以使用缓存
- 4xx:客户端错误状态码,表示请求有错误
- 400 Bad Request:请求参数错误
- 401 Unauthorized:未认证,需要登录
- 403 Forbidden:权限不足,禁止访问
- 404 Not Found:资源不存在
- 405 Method Not Allowed:请求方法不允许
- 429 Too Many Requests:请求过多,被限流
- 5xx:服务器错误状态码,表示服务器处理出错
- 500 Internal Server Error:服务器内部错误
- 502 Bad Gateway:网关错误,上游服务异常
- 503 Service Unavailable:服务不可用,通常是过载或维护
- 504 Gateway Timeout:网关超时,上游服务响应超时
常见响应头
- Content-Type:响应体的类型和编码
- Content-Length:响应体的长度
- Content-Encoding:响应体的压缩方式,gzip、deflate等
- Cache-Control:缓存控制,max-age=3600表示可以缓存3600秒
- Set-Cookie:设置Cookie,服务器让客户端保存Cookie
- Location:重定向的目标地址
- Access-Control-Allow-Origin:跨域控制,允许哪些域名跨域访问
- ETag:资源的标识,用于缓存验证
- Last-Modified:资源最后修改时间
HTTP的发展
- HTTP/0.9:1991年发布,只有GET方法,只能返回HTML
- HTTP/1.0:1996年发布,支持多种请求方法,支持多媒体
- HTTP/1.1:1999年发布,是目前使用最广泛的版本,支持长连接、虚拟主机、断点续传等
- HTTP/2:2015年发布,二进制协议,多路复用,头部压缩,服务器推送,性能比HTTP/1.1提升很多
- HTTP/3:基于QUIC协议,使用UDP传输,更快的连接建立,队头阻塞问题解决,性能更好,目前正在普及中
HTTPS协议
HTTPS就是HTTP + SSL/TLS,在HTTP和TCP之间加了一层SSL/TLS加密层,解决了HTTP明文传输的问题:
- 加密:传输的数据都是加密的,第三方无法窃听内容
- 完整性:数据不会被篡改,篡改会被检测到
- 身份认证:确认网站的真实身份,防止中间人攻击
HTTPS的握手过程:
- 客户端发送Client Hello,支持的加密套件、随机数等
- 服务器返回Server Hello,选择加密套件,发送证书
- 客户端验证证书合法性,生成预主密钥,用服务器公钥加密后发送给服务器
- 服务器用私钥解密得到预主密钥,双方各自生成会话密钥
- 后续的HTTP数据都用会话密钥加密传输
DNS协议(域名系统)
DNS的作用是把域名(比如www.example.com)解析为对应的IP地址,因为网络层只认IP地址,不认域名。
DNS的工作原理
DNS是一个分布式的层次数据库,采用递归查询和迭代查询相结合的方式:
- 客户端查询本地DNS缓存,有就直接返回
- 没有的话向本地DNS服务器发起递归查询,本地DNS服务器负责帮客户端查询
- 本地DNS服务器如果有缓存直接返回,否则进行迭代查询:
- 先查根域名服务器,得到顶级域(.com)服务器地址
- 查顶级域服务器,得到二级域(example.com)服务器地址
- 查权威域名服务器,得到www.example.com的IP地址
- 本地DNS服务器把结果返回给客户端,同时缓存结果
DNS记录类型
常见的DNS记录类型:
- A记录:域名指向IPv4地址
- AAAA记录:域名指向IPv6地址
- CNAME记录:域名指向另一个域名,相当于别名
- MX记录:邮件交换记录,指向邮件服务器地址
- TXT记录:文本记录,通常用来做验证,比如域名所有权验证、SPF反垃圾邮件
- NS记录:域名服务器记录,指定该域名由哪个DNS服务器解析
DNS优化
- DNS缓存:浏览器、操作系统、本地DNS服务器都会缓存DNS解析结果,减少查询时间
- 域名预解析:提前解析需要用到的域名,减少用户访问时的延迟
- 智能DNS:根据用户地理位置返回最近的服务器IP,提升访问速度
其他常见应用层协议
FTP(文件传输协议)
- 用于在主机之间传输文件,默认端口20(数据端口)和21(控制端口)
- 有主动模式和被动模式两种工作模式
- 明文传输,不安全,现在通常使用SFTP(SSH File Transfer Protocol)代替,基于SSH加密传输
SSH(安全外壳协议)
- 用于远程登录服务器,默认端口22
- 加密传输,安全可靠,代替了传统的明文传输的Telnet协议
- 还可以用来做端口转发、隧道、文件传输(SFTP/SCP)
SMTP/POP3/IMAP(邮件协议)
- SMTP:简单邮件传输协议,默认端口25,用于发送邮件
- POP3:邮局协议版本3,默认端口110,用于接收邮件,下载到本地后服务器上的邮件会被删除
- IMAP:互联网邮件访问协议,默认端口143,用于接收邮件,邮件保存在服务器上,可以多端同步
WebSocket
- HTML5提供的全双工通信协议,基于TCP,默认端口80(ws)和443(wss加密)
- 握手阶段使用HTTP协议,握手成功后变成TCP连接,双方可以实时双向发送数据
- 适合需要实时通信的场景:聊天、实时推送、在线游戏、协同编辑等
RESTful API设计
REST(Representational State Transfer)是现在最流行的API设计风格:
- 资源:每个URL对应一个资源
- 用HTTP方法表示操作:GET获取、POST创建、PUT更新、DELETE删除
- 无状态:每个请求包含所有必要的信息,服务器不保存状态
- 统一接口:使用标准的HTTP状态码、请求头、响应头
- 响应通常使用JSON格式
GraphQL
GraphQL是Facebook推出的API查询语言,是REST的替代方案:
- 客户端可以精确指定需要的数据结构,避免过度获取或者数据不足
- 一个请求可以获取多个资源,减少请求次数
- 强类型 schema,便于校验和文档生成
- 适合复杂的前端应用,尤其是移动应用,可以减少请求数量,提升性能
思考问题
- HTTP协议是无状态的,怎么实现保持用户登录状态?
- HTTP状态码301和302有什么区别?分别适合什么场景?
- HTTPS是怎么保证传输安全的?为什么HTTPS可以防窃听和篡改?
- DNS的工作原理是什么?输入URL到浏览器显示页面的过程中,DNS起到什么作用?