HTTP学习笔记(二)

451 阅读8分钟

一、 输入网址以后, 发生了什么?

  1. 如果输入的是域名, 首先会进行域名解析, 找到IP地址
  2. 进行TCP三次握手, 建立链接
  3. 浏览器发送请求报文, 服务器返回获取图片,css等静态资源或ajax请求数据
  4. 拿到响应处理响应(响应的数据也可能是CDN服务器, 负载均衡服务器等其他中间缓存直接返回, 并不会真正到达服务器), 绘制dom, 执行js脚本等
  5. 如果链接断开, 就会执行四次挥手的过程 如图所示:

Wireshark HTTP抓包

  • 第一行为三次握手的过程
  • 第二行和第三行分别为2次数据请求及响应
  • 因为长连接的原因, 并没有出现四次挥手的过程

二、TCP三次握手

  • 第一次握手 ([SYN], Seq = x): 客户端发起链接, 并且发送SYN标志位, 以及初始序列号X, 发送完成后,客户端进入 SYN_SEND 状态

  • 第二次握手 ([SYN, ACK], Seq = y, ACK = x + 1):

服务器返回确认包ACK, 同时发送SYN包回去, ACK = x + 1 表示确定收到, Seq = y 是为了让客户端确认收到. 发送完成后, 服务端进入 SYN_RCVD 状态

  • 第三次握手 ([ACK], ACK = y + 1):

客户端再次发送确认包ACK, ACK = y + 1, 表示确认收到了服务器的包. 客户端发送完毕后, 进入ESTABLISHED 状态, 服务器收到这个包以后, 也进入 ESTABLISHED 状态. 至此 TCP握手结束

TCP 三次握手

为什么不是2次握手? 如果服务器应答有, 客户端不进行最后的确认, 服务器就不能确定客户端是否可以收到消息
为什么不是4次握手? 3次握手的过程已经可以保证客户端和服务器可以互相发送消息, 互相接收消息, 就不用再多一次浪费资源

三、TCP数据请求/响应

  • 客户端发起数据请求 (GET / HTTP/1.1):

客户端在通过三次握手建立链接后, 通过TCP发动一个请求, 比如GET请求

  • 服务器响应GET请求 ([ACK], Seq = x):

服务器收到请求以后, 给客户端发送ACK确认包, 表示已经收到请求

  • 服务器发送请求数据 (HTTP/1.1 200 OK):

服务器找到对应的URI以后, 将数据返回给客户端, 状态码为200 (或者是其他状态的返回)

  • 客户端接收确认 ([ACK], Seq = y):

客户端接收到具体数据后, 发送ACK确认包, 表示已经收到数据

HTTP 数据请求

四、TCP四次挥手

  • 第一次挥手 ([FIN], Seq = x):

客户端发送FIN标记的包, 告诉服务器需要关闭连接, 发送完毕后进入 FIN_WAIT_1 状态, 此时客户端将不会在发送数据, 但依然可以接收数据

  • 第二次挥手 ([ACK], ACK = x + 1):

服务器发送ACK确认包, 告诉客户端收到了关闭的请求. 服务器进入 CLOSE_WAIT 状态, 客户端收到这个包以后进入 FIN_WAIT_2. 此时服务器可能还在继续给客户端发送数据

  • 第三次挥手 ([FIN], Seq = y):

服务器给客户端的数据发送完毕后, 发送FIN标记包, 告诉客户端准备关闭, 发送完成后, 服务器进入 LAST_ACK 状态

  • 第四次挥手 ([ACK], ACK = y + 1):

客户端收到服务器的关闭请求, 发送ACK确认包, 进入 TIME_WAIT 状态, 等待服务器可能要求重传的ACK包

服务器收到ACK包以后, 关闭连接, 进入CLOSED 状态. 服务器在没有收到重传的ACK包以后也关闭连接, 进入 CLOSED, 至此, 四次挥手结束

TCP 四次挥手

为什么不是3次挥手? 因为如果只收到客户端的请求就关闭的话, 可能当前数据请求的数据还没有发送完, 会造成数据丢失. 所以要服务器把数据发送完毕以后,在进行一次确认关闭

五、HTTP报文结构

  1. HTTP协议的的请求报文和响应报文结构基本相同, 由三大部分组成:
    • 起始行: 请求或响应的基本信息
    • 头部字段: 报文的详情属性, 以key-value的形式存在
    • 消息正文: 实际传输的数据, 可能是文本, 图片等 其中前2部分我们经常合称为 请求头 或 响应头, 也就是 header, 而第三部分则被称为 body
  1. HTTP协议规定, 报文必须有header, 但可以没有body
  2. header 后必须要有一个空行
  1. 起始行根据请求和响应分为 请求行 和 状态行 2种
  • 请求行: 请求报文中的起始行就是请求行, 请求行由3部分组成: 请求方法 + 请求目标 + 版本号, 如: GET / HTTP/1.1

  • 状态行: 响应报文中的起始行叫做状态行, 也是由三部分组成: 版本号 + 状态码 + 原因, 如: HTTP/1.1 200 OK

  1. 头部字段是由 key-value的形式组成常用的有:

    • 通用字段: 在请求头和响应头中都可以出现
      Date: 表述报文创建的时间

    • 请求字段: 仅出现在请求头
      Host: 请求的主机(必须传)
      User-Agent: 描述发起请求的客户端, 如Chrome, Safari

    • 响应字段: 仅出现在响应头
      Server: 表示服务器当前的Web服务软件及版本号 (通常不会真正返回具体的, 容易被攻击)

    • 实体字段: 描述body的 额外信息
      Content-Length: 表示报文body的长度

六、常用的标准请求方法

  • GET: 获取资源. 从服务器读取,或者下载数据
  • HEAD: 获取资源的元信息. 可以减少响应消息体的大小
  • POST: 向服务器提交数据. 相当于写入或上传数据(RFC建议新建操作)
  • PUT: 类似POST(RFC建议更新操作)
  • DELETE: 删除资源

七、URI的组成

URI是指 统一资源标识符, 他包含 URL和URN 2部分. URI的格式由 scheme, host:port, path和query 四个部分组成.

  • scheme: 表示资源所使用的协议, 如http,ftp, mail等 (协议后必须是 :// 三个字符, 将前后2个部分分开)
  • host:port: 表示主机名, 通常是 主机名+端口号的形式, 主机名也可以是IP地址的形式. 主机名必须要有, 否则就找不到对应的服务器, 端口号如果不写, 则会根据scheme使用默认的端口号. 如: http默认为80, https默认为443
  • path: 有了协议名+主机名+path, 浏览器就可以直接访问资源了
  • query: 表示查询参数. 通过查询参数, 可以给服务器更多的信息, 来帮助服务器返回更准确的数据 URI的编码: 在一些特殊的URI中, 特殊的字符会导致URI解析失败, 所以就引入了URI 的编码

八、常见的响应状态码

  • 1xx: 提示信息, 表示当前处于中间, 需要后续操作
  • 2xx: 成功, 表示报文已收到并且正确处理
    200 OK: 一切正常
    204 No Content: 与200相似, 只不过是响应信息中没有body
    206 Partial Content: 表示处理成功了一部分数据, 但不是全部. 是HTTP断点续传的基础
  • 3xx: 重定向, 表示资源位置改变, 需要重新请求
    301 Moved Permanently: 永久重定向, 表示资源不存在了
    302 Found : 临时重定向, 表示资源还在, 但是暂时需要通过其他URI访问
    304 Not Modified: 缓存重定向, 表示重定向已经缓存到文件
  • 4xx: 客户端错误, 表示报文错误, 服务器无法处理
    400 Bad Request: 表示请求报文有误, 单具体那里错了没有明确给出
    403 Forbidden: 表示服务器禁止访问资源
    404 Not Found: 表示资源在服务器上没有找到
    405 Method Not Allowed: 请求方式错误, 比如POST使用GET请求
    408 Request Timeout: 请求超时
  • 5xx: 服务器错误, 表示服务器内部处理时发生错误
    500 Internal Server Error: 这是一个通用的服务器错误码, 具体原因也不知道
    501 Not Implemented: 表示现在请求的功能还不支持
    502 Bad Geteway: 表示服务器自身工作正常, 访问后端服务器时发生了错误
    503 Service Unavailable: 表示服务器现在忙, 暂时无法响应服务, 需要延迟后再次请求

九、HTTP的特点

  • 灵活可扩展 HTTP从最开始的设计就非常的简单, 在不断的更新中, body从仅TXT到现在的图片,音频等 可以看到他的可扩展性

  • 可靠传输 因为HTTP是基于TCP/IP协议的, 所以他也继承了TCP可靠的特点. 可靠表示: 在数据传输过程中, 尽量保证数据完整的送达

  • 应用层协议 HTTP是少有的, 基于应用层并且功能非常的丰富

  • 请求-应答模式 HTTP使用的是请求-应答的通信模式, 所以双方肯定是先发起请求和链接,然后进行数据传输

  • 无状态 无状态指的是客户端或服务端不会对本次链接进行记录, 下次的链接需要重新进行. 但是由于HTTP是可扩展的, 所以就有了一些扩展, 让链接变得有状态(Cookie等)

系列目录

HTTP学习笔记(一)

HTTP学习笔记(二)

HTTP学习笔记(三)

HTTP学习笔记(四)

HTTP学习笔记(五)

HTTP学习笔记(六)