主机应用程序是怎么完成HTTP通信?

1.基础理论

OSI开放系统互联
定义了网络框架,以层为单位实现协议,同时控制权逐层传递。

OSI实际并没有落地,TCP/IP 5层协议栈是目前主流的落地实现

1.1. TCP/IP 5层协议栈

TCP/IP协议栈不止是传输层tcp/网络层ip, 还包括应用层等,这是一个协议簇,只是因为TCP/IP很具代表性。

不管是OSI还是TCP/IP5层协议栈,均会出现应用程序和操作系统边界(代码执行在用户态/内核态)。

image

边界调用被称为系统调用system callsocket api便是TCP/IP协议栈中应用层的网络编程接口。

1.2. 网络主机是如何通信的?

tcp/ip协议栈 对应tcpdump左下视图 备注
应用层 应用层对请求包做格式定义, 比如http
传输层 TCP、UDP Transmission Control Protocol 传输层协议加上双方通信的端口号,确定双方主机上的应用程序
网络层 (IP,ICMP,ARP协议) Internet Protocl Version 4 网络层加上双方的IP地址(可能由DNS协议给出), 确定双方的网络位置
链路层 (以太网协议) Ethernet2 最后链路层加上了 MAC地址(通过ARP协议),确认双方物理位置,并对数据包分组,形成数据帧Frames, 最后通过传输介质送到对方主机

当源主机和目标主机不在同一个网络(子网)内时,源主机会将数据包发送到其默认网关(通常是路由器)的 MAC 地址。这是因为默认网关负责将数据包转发到其他网络。

以下是详细的工作流程:

1>. 确定目标网络

  • 源主机首先检查目标 IP 地址是否在同一个子网内。这是通过比较源主机的子网掩码和目标 IP 地址来完成的。

2>. 选择默认网关

  • 如果目标 IP 地址不在同一个子网内,源主机会选择将数据包发送到其默认网关。

3>. ARP 请求

  • 源主机使用地址解析协议(ARP)来确定默认网关的 MAC 地址。它会在本地网络上广播一个 ARP 请求,询问谁拥有默认网关的 IP 地址。
  • 默认网关响应这个请求,提供它的 MAC 地址。

4>. 封装数据包

  • 源主机将数据包的目标 MAC 地址设置为默认网关的 MAC 地址,而目标 IP 地址保持为最终目标的 IP 地址。
  • 数据包被封装在一个以太网帧中,并通过本地网络发送到默认网关。

5>. 路由转发

  • 默认网关接收到数据包后,根据其路由表,决定如何将数据包转发到目标网络。这可能涉及多个路由器的转发,直到数据包到达目标网络。

6>. 最终到达目标主机

  • 一旦数据包到达目标网络,最后一个路由器会使用 ARP 找到目标主机的 MAC 地址,并将数据包发送给目标主机。

这个过程确保了即使源主机和目标主机不在同一个网络中,数据包也能够通过网络设备(如路由器)进行有效传输。

1.3. TCP/UDP

  • TCP: 传输控制协议Transmission Control Protocol是面向连接的、可靠的,基于字节、双向传输层协议。 开发者对于tcp一定不要带入http请求-响应模型,tcp是双向通信流。

  • UDP: 用户数据报协议User Datagram Protocol是面向消息的传输服务,传输的数据是有边界的。

区别:
TCP可靠性是tcp三次握手的基础,在此之上,增加了seq、ack数据确认机制、 拥塞控制, 其中ack= seq+len(data)。

UDP: 想法就发,不用三次握手建立连接。

我们目前常见的应用场景底层都是tcp,比如http请求、sql数据库请求。建立TCP连接之后,才能做http请求、sql请求,tcp连接很耗时,故服务器都存在连接池化机制。


2. 正文: HTTP请求时怎么到达对方主机并与应用程序交互。

HTTP: 超文本传输协议 Hypertext Transfer Protocol,

Q: HTTP 1.1 在应用层是纯文本协议,但是记忆中底层都是二进制传输, 这个到底怎么理解?

A: HTTP 1.1 在应用层是文本协议: 其核心的协议头:请求行、响应行、请求头都是纯文本,使用空格、换行符、冒号来解析, 到了传输层(TCP,UDP)就需要变成该层规定的二进制传输。

在传输层(TCP), 其不care具体的应用层文本,有自己的二进制拆包/粘包算法。

2.1. TCP粘包/拆包

tcp协议规定字节流式传输

  • 正常的理想情况,应用层下发的两个原始包恰好满足TCP缓冲区的大小或达到TCP等待时长,分别发送两个包;
  • 粘包:两个包较小,间隔时间短,发生粘包,合并成一个包发送;
  • 拆包:一个包过大,超过缓存区大小,拆分成两个或多个包发送;
  • 拆包和粘包:Packet1过大,进行了拆包处理,而拆出去的一部分又与Packet2进行粘包处理。

应用层的请求内容,
经过TCP的二进制拆、粘包,加上固定的20字节的TCP首部(包含端口信息,确定通信应用),
经过网络层, 加上20+字节的IP首部(包含IP信息,确定通信主机)。


Q: 到这里我们就可以想象为什么HTTP1.1 是请求-响应模型了,而不能在一个tcp连接上同时发起多个请求。

A:HTTP 1.1 的纯文本, 可能会被tcp传输层协议拆包,如果能同时发送请求,对端收到的分包可能不是预期的顺序,导致无法组包。
HTTP2 是二进制协议,应用上兼容HTTP1.1的纯文本协议,被传输层分包后形成二进制分帧, 不是依赖内容格式的纯文本, 二进制帧有记录请求标识和分帧长度的元信息

image

image

image

所以HTTP2二进制分帧到达对端 (即使发出多个请求,产生多个混杂的分帧),对端依旧可以根据二进制分帧中的帧头元信息,再次组包。


posted @ 2023-05-09 20:08  码甲哥不卷  阅读(577)  评论(0)    收藏  举报