( 该图由AI制作 学习AI绘图 )
目录
将 HTTP 请求消息交给协议栈
对较大的数据进行拆分
使用 ACK 号确认网络包已收到
根据网络包平均往返时间调整 ACK 号等待时间
返回 ACK 号的等待时间(这个等待时间叫超时时间)
使用窗口有效管理 ACK 号
接收 HTTP 响应消息
将 HTTP 请求消息交给协议栈
当控制流程从 connect 回到应用程序之后 (图中的②结束)
进入数据收发阶段(
从应用程序调用
write
将要发送的数据交给协议栈
开始
(
图
③
)
)
协议栈收到数据后执行发送操作
协议栈收到数据
会将数据存放在内部的发送
缓冲区
中
等待应用程序的下一段数据
要积累多少数据才能发送
,
不同种类和版本的操作系统会有所不同
补充:如何判断何时发送
1:是每个网络包能容纳的数据长度
根据一个叫作 MTU 的参数来进行判断 。 MTU 表示一个网络包的最大长度 , 在以太 网中一般是 1500 字节 ( 图 ) 。 MTU 是包含头部的总长度 , 因此需要从 MTU 减去头部的长度 , 然后得到的长度就是一个网络包中所能容纳的最大 数据长度 , 这一长度叫作 MSS 。 当从应用程序收到的数据长度超过或者接 近 MSS 时再发送出去 , 就可以避免发送大量小包的问题了2:另一个判断要素是时间
当应用程序发送数据的频率不高的时候 , 如果每次都等到长度接近 MSS 时再发送 ,可能会因为等待时间太长而造成发 送延迟 , 这种情况下 , 即便缓冲区中的数据长度没有达到 MSS , 也应该果 断发送出去 。 为此 , 协议栈的内部有一个计时器 , 当经过一定时间之后 , 就会把网络包发送出去
对较大的数据进行拆分
发送缓冲区中的数据会被以
MSS
长度为单位进行拆分
,
拆分出来的每块数据会被放进单独的网络包中
根据发送缓冲区中的数据拆分的情况
,
当判断需要发送这些数据时
,
就在每一块数据前面加上
TCP
头部
,
并根据套接字中记录的控制信息标记发送
方和接收方的端口号
,
然后交给
IP
模块来执行发送数据的操作
使用 ACK 号确认网络包已收到
网络包已经装好数据并发往服务器了
TCP
模块在拆分数据时
,
会先算好每一块数据相当于从头开始的第几个字节
接下来在发送这一块数据时
,
将算好的字节数写在
TCP
头部中
“序号”字段就是派在这个用场上的。
然后
,
发送数据的长度也需要告知接收方
通过这些信息,接收方还能够检查收到的网络包有没有遗漏
在客户端向服务器发送数据的同时,服务器也会向客户端发送数据
我们只要增加一种左右相反的情形
明白原理之后我们来看一下实际的工作过程
客户端在连接时,需要计算出,与从客户端,到服务器,方向,通信相关的,序号初始值
,
并
将这个值,发送给服务器
(
图
①
)。
服务器会通过这个初始值计算出
ACK
号并返回给客户端
(
图
②
)
这一机制非常强大
。
通过这一机制
,
我们可以确认接收方有没有收到某个包
,
如果没有收到则重新发送
,
这样一来
,
无论网络中发生任何错误
,
我们都可以发现并采取补救措施
(
重传网络包
)。
反过来说
,
有了这一机
制
,
我们就不需要在其他地方对错误进行补救了
因此,网卡、集线器、路由器都没有错误补偿机制,一旦检测到错误就直接丢弃相应的包
通过“序号”和“ACK 号”可以确认接收方是否收到了网络包
根据网络包平均往返时间调整 ACK 号等待时间
返回 ACK 号的等待时间(这个等待时间叫超时时间)
等待时间需要设为一个合适的值
,
不能太长也不能太短
,
但这谈何容易
根据服务器物理距离的远近
,
ACK
号的返回时间也会产生很大的波动
,
而且我们还必须考虑到拥塞带来的影响
。
因此
,
TCP
采用了动态调整等待时间的方法
,
这个等待时间是根据
ACK
号返回所需的时间来判断的
。
具体来说
,
TCP
会在发送数据
的过程中持续测量
ACK
号的返回时间
,
如果
ACK
号返回变慢
,
则相应
延长等待时间
;
相对地
,
如果
ACK
号马上就能返回
,
则相应缩短等待
时间
使用窗口有效管理 ACK 号
为了减少这样的浪费
,
TCP
采用图
(b
)
这样的滑动窗
口方式来管理数据发送和
ACK
号的操作
。
所谓滑动窗口
,
就是在发送一
个包之后
,
不等待
ACK
号返回
,
而是直接发送后续的一系列包
。
这样一
来
,
等待
ACK
号的这段时间就被有效利用起来了
可能会出现发送包的频率超过接收方处理能力的情况
接收 HTTP 响应消息
到这里
,
我们已经讲解完,协议栈接到,浏览器的委托后,发送
HTTP
请求消息,的一系列操作过程了
。
对于响应消息
,
浏览器需要进行接收操作
,
这一操作也需要协议栈的参与
浏览器在委托协议栈发送请求消息之后
,
会调用
read
程序
控制流程会通过
read
转移到协议栈
随着控制流程转移,应用程序也会进入暂停状态
协议栈尝试从接收缓冲区中取出数据并传递给应用程序
协议栈会检查收到的数据块和
TCP
头部的内容
,
判断是否有数据丢失
,
如果没有问题则返回
ACK
号
。
然后
,
协议栈将数据块暂存到接收缓冲区中
,
并将数据块按顺序连接起来还原出
原始的数据
,
最后将数据交给应用程序