传输原理
TCP通过 “ 发送 — 应答 (ACK确认)”来确保传输的可靠性,它是端到端传输的。
TCP传输是分段的,一个HTTP响应报文会被操作系统切成多个MSS(Maximum Segment Size)大小的段,直到接收端接受到完整的报文为止。在此过程中,报文分段按照顺序进行发送,每个报文段在发送时,会做顺序编号,以便能够完整正确地组装。
MSS:Maximum Segment Size 最大报文段长度,是TCP协议的一个选项,用于在 TCP连接建立时,收发双方协商通信时每一个报文段所能承载的最大数据长度(不包 括文段头)。如果MSS选项数据为512,则表示该报文段的发送方可以处理的最大报 文段长度为512字节(不包括TCP与IP协议头长度)。主机一般默认MSS为536字节。
image.png
端口号:
1)表示同一个计算机上的不同进程
2)源端口号和目标端口号都是占用了两个字节
3)TCP的源端口号和目标端口号预计IP报文中的源IP和目标IP确认一条唯一的TCP连接
序号:
4个字节
确认序号:
ack,占四个字节
控制位:
URG、ACK、PSH、RST、SYN、FIN
TCP 的数据是通过名为 IP 分组( 或 IP 数据报) 的小数据块来发送的。HTTP就是“HTTP over TCP over IP” 这个“协议栈” 中的最顶层了。 其安全版本 HTTPS就是在 HTTP 和 TCP 之间插入了一个( 称为 TLS 或 SSL的) 密码加密层。
HTTP 要传送一条报文时, 会以流的形式将报文数据的内容通过一条打开的TCP 连接按序传输。 TCP 收到数据流之后, 会将数据流砍成被称作段的小数据块, 并将段封装在 IP 分组中, 通过因特网进行传输。 所有这些工作都是由TCP/IP 软件来处理的, HTTP 程序员什么都看不到。
每个 TCP 段都是由 IP 分组承载, 从一个 IP 地址发送到另一个 IP 地址的。 每 个 IP分组中都包括:
一个 IP 分组首部(通常为 20 字节)
一个 TCP 段首部(通常为 20 字节)
一个 TCP 数据块(0 个或多个字节)
IP 首部包含源和目的 IP 地址、 长度和其他一些标记。 TCP 段的首部包含了TCP端口号、 TCP 控制标记, 以及用于数据排序和完整性检查的一些数字值。
image.png
TCP 连接是通过 4 个值来识别的:
< 源 IP 地址、 源端口号、 目的 IP 地址、 目的端口号 >
这 4 个值一起唯一地定义了一条连接。 两条不同的 TCP 连接不能在同一时刻拥有 4 个完全相同的地址组件值
image.png
有些连接共享了相同的目的端口号(C 和 D 都使用目的端口号 80)。 有些连接使用了相同的源 IP 地址(B 和 C)。 有些使用了相同的目的 IP 地址(A 和 B, C和 D)。但没有两个不同连接所有的 4 个值都一样。
滑动窗口协议
将TCP与UDP这样的简单传输协议区分开来的两种协议不同的传输数据的质量。
TCP对于发送数据进行跟踪,这种数据管理需要协议有以下两大关键功能:
可靠性:保证数据确实到达目的地。如果未到达,能够发现并重传。
数据流控:管理数据的发送速率,以使接收设备不致于过载。
要完成这些任务,整个协议操作是围绕滑动窗口确认机制来进行的。因此,理解了滑动窗口,也就是理解了TCP。
1)在我们滑动窗口协议之前,我们如何来保证发送方与接收方之间,每个包都能被收到,并且是按次序的呢?
image.png
问题:吞吐量非常的低。我们发完包1,一定要等确认包1,我们才能发送第二个包。
2)那么我们就不能先连发几个包等他一起确认吗?这样的话速度更快,吞吐量更高
image.png
问题:如果过多的源同时以很快的速度发送大量的数据包,而此时接收方并没有如此高的接收数据的能力,因此极易导致网络的拥塞。
3)滑动窗口协议(Sliding Window Protocol)
该协议是 TCP协议 的一种应用,用于网络数据传输时的流量控制,以避免拥塞的发生。该协议允许发送方在停止并等待确认前发送多个数据分组。由于发送方不必每发一个分组就停下来等待确认。因此该协议可以加速数据的传输,提高网络吞吐量。滑动窗口算法其实和这个是一样的,只是用的地方场景不一样。
如果我们在任一时间点对于这一过程做一个“快照”,那么我们可以将TCP buffer中的数据分为以下四类,并把它们看作一个时间轴:
- 已发送已确认 数据流中最早的字节已经发送并得到确认。这些数据是站在发送设备的角度来看的。
- 已发送但尚未确认 已发送但尚未得到确认的字节。发送方在确认之前,不认为这些数据已经被处理。
- 未发送而接收方已Ready 设备尚未将数据发出,但接收方根据最近一次关于发送方一次要发送多少字节确认自己有足够空间。发送方会立即尝试发送。
-
未发送而接收方Not Ready 由于接收方not ready,还不允许将这部分数据发出。
image.png
说明:
1)灰色1号2号3号包已经发送完毕,并且已经收到Ack。这些包就已经是过去式。
2)4、5、6号包是黄色的,表示已经发送了。但是并没有收到对方的Ack,所以也不知道接收方有没有收到。
3)7、8、9号包是淡蓝色的。是我们还没有发送的。这些淡蓝色也就是我们接下来马上要发送的包。
4)后面的10-15还没有被读进内存。要等4号-9号包有接下来的动作后,我们的包才会继续往下发送。
正常情况:
image.png
可以看到4号包对方已经被接收到,所以被涂成了灰色。“窗口”就往右移一格。我们就把11号包读进了我们的缓存。进入了“待发送”的状态。8、9号包已经变成了黄色,表示已经发送出去了。接下来的操作就是一样的了,确认包后,窗口往后移继续将未发送的包读进缓存,把“待发送“状态的包变为”已发送“。
丢包情况:
有可能我们包(5-11)发过去,对方的Ack丢了。也有可能我们的包并没有发送过去。从发送方角度看就是我们没有收到Ack。
image.png
发生的情况:一直在等Ack。如果一直等不到的话,我们也会把读进缓存的待发送的包也一起发过去。但是,这个时候我们的窗口已经发满了。所以并不能把12号包读进来,而是始终在等待5号包的Ack。
问题:如果我们这个Ack始终不来怎么办呢?
超时重发/重传:
原理是在发送某一个数据以后就开启一个计时器,在一定时间内如果没有得到发送的数据报的ACK报文,那么就重新发送数据,直到发送成功为止。
影响超时重传机制协议效率的一个关键参数是重传超时时间(RTO,Retransmission TimeOut)。RTO的值被设置过大过小都会对协议造成不利影响。
1)RTO设长了,重发就慢,没有效率,性能差。
2)RTO设短了,重发的就快,会增加网络拥塞,导致更多的超时,更多的超时导致更多的重发。
3)连接往返时间(RTT,Round Trip Time),指发送端从发送TCP包开始到接收它的立即响应所消耗的时间。
在 Unix 以及 Windows 系统中,最初其重发超时的默认值一般设置为6秒(重发时间必须是0.5秒的倍数)左右。数据被重发之后若还是收不到确认应答,则进行再次发送。此时,等待确认应答的时间将会以2倍、4倍的指数函数延长。
此外,数据也不会被无限、反复地重发。达到一定重发次数之后,如果仍没有任何确认应答返回,就会判断为网络或对端主机发生了异常,强制关闭连接,并且通知应用通信异常强行终止。
网友评论