主机应用程序是怎么完成HTTP通信?
1.基础理论
OSI开放系统互联
定义了网络框架,以层为单位实现协议,同时控制权逐层传递。

OSI实际并没有落地,TCP/IP 5层协议栈是目前主流的落地实现。
1.1. TCP/IP 5层协议栈
TCP/IP协议栈不止是传输层tcp/网络层ip, 还包括应用层等,这是一个协议簇,只是因为TCP/IP很具代表性。
不管是OSI还是TCP/IP5层协议栈,均会出现应用程序和操作系统边界(代码执行在用户态/内核态)。

边界调用被称为系统调用system call, socket 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的纯文本协议,被传输层分包后形成二进制分帧, 不是依赖内容格式的纯文本, 二进制帧有记录请求标识和分帧长度的元信息。



所以HTTP2二进制分帧到达对端 (即使发出多个请求,产生多个混杂的分帧),对端依旧可以根据二进制分帧中的帧头元信息,再次组包。
本文来自博客园,作者:{有态度的马甲},转载请注明原文链接:https://www.cnblogs.com/JulianHuang/p/17386121.html
欢迎关注我的原创技术、职场公众号, 加好友谈天说地,一起进化

浙公网安备 33010602011771号