绪
运输层将网络层在两个端系统之间的交付服务,扩展到运行在两个不同端系统上的应用层进程之间的交付服务,同时提供了额外的逻辑通信服务
简单概念
一般运输层传输的数据叫做报文段,而网络层传输数据称为数据报,但由于UDP与网络层数据报很类似,个别也会将UDP传输的数据称为数据报
多路复用、多路分解即将网络层所提供的主机到主机的交付服务扩展为两个端进程间的交付服务,其中多路复用是指发送时将不同进程的数据通过不同的socket发送出去,多路分解为将接受到的网络层数据分解到不同的socket中
端口号是一个16比特的数字,范围为065535,其中01023为周知端口号,是被系统保留并被严格控制的
套接字(socket)其实是由源端口号、源IP、目标端口号、目标IP四个字段确定的,即一个连接对应一个套接字,同时不要忘了一个端口可以同时维护多个连接
UDP
UDP其实很简单,只是在网络层的数据报基础上增加了部分多路复用和分解的报头。也就是说UDP如同网络层一样,只提供尽力的交付服务,不保证完整、有序,那我们选择UDP的场景有哪些呢?
- 可以忍受一定的数据丢失,但要求强实时性 因为不要建立连接,同时没有拥塞控制,所以UDP的网络时延小
- 性能更好 因为不需要维护连接,所以UDP的性能要更好,可以支持更多的活跃客户机
- 网络开销小 因为功能简单所以UDP的报文头短小,所以报文整体要比TCP小
TCP
TCP提供的一个重要服务便是可靠传输,即保证数据完整、有序,且在合理的时间范围内。我们知道传输层所依赖的网络层并不是可靠的,那TCP是如何在此基础上实现了可靠传输协议呢?在本小节中,我们会在一个不断接近真实的网络模型上逐步建立一个可靠传输协议。希望能够帮助大家更加深入的理解TCP的各个功能的意义
完全可靠的信道
最简单的,我们假设网络是完全可靠的,不会丢失数据、不会拥塞。那么我们该如何构建该协议呢?
很简单,发送方发送数据,然后接收方收到数据后发送一个反馈,发送方接收到反馈后继续发送,甚至当我们可以约定两者的速度匹配,则不需要接收方发送反馈,这样我们完成了可靠传输协议rdt1.0
会出现比特差错的信道
好,我们现在再增加一点真实性,即信道中传输的数据会出现比特差错(即0、1跳变),现在该怎么办呢?
也很简单,只需要在rdt1.0的基础上增加
- 差错检测 检测报文数据完整性有很多办法,常用的包括奇偶校验位、摘要等
- 反馈接收 即发送方获取接收方正确收到数据后的反馈
- 重发 当接收方发送的反馈是数据错误时则重发数据
好了,增加这几个功能后我们便可以解决比特差错的问题了。oh,yeah!
等等,反馈本身要是也出错了怎么办?
所以,还差一点,那就是当反馈本身也出错时(即发送方收到了‘含糊不清’的反馈)则也默认重发数据,但这又会有个问题,接收方万一之前正确接收了,现在又发送,他又接收了怎么办?解决办法就是在发送报文中添加重传标记,标明数据会重发
至此,我们就有了更加健壮的rdt2.0了
会出现丢包、比特差错的信道
道高一尺,魔高一丈。真实的网络环境中不仅数据会跳变,还会丢包。即发送方和接收方发送的任何报文段都可能丢失。解决这个问题其实很简单,只需要在发送方增加倒数计时器即可。当发送方发送数据后便开始计时,若超时未得到响应,则重发数据。至于这个超时如何确定,一般会设置为报文段的一次往返时间。
rdt3.0完成。截止目前,我们已经有了一个基本可以在真实网络环境中工作的简易TCP了
以流水线方式实现
rdt3.0其实已经能够真实运行了,但还存在一个很大的缺陷,那就是性能很差。因为发送方和接收方之间的每一步基本都是“停等”的。我们可以通过流水线的方式来加速数据传输,但一旦使用流水线,那么发送和接收的模型都会更加复杂,他们必须得做到以下几点
- 增加编号 即每个分组要增加一个唯一的序号,方便流水线管理分组
- 增加缓存 即发送方和接收方都要增加一个缓冲区,用来缓存双方尚未确认的分组
- 解决差错 流水线方式的话,因为是批量发送数据,出现错误后处理难度会较之刚才更大,TCP使用回退N步和选择重传两种策略解决这个问题
回退N步
发送方的发送模型大概是这样的,发送方不断的发送数据,直至一个阈值(这也叫做发送窗口长度,这样做也是为了防止网络拥塞),然后缓存起来这些已发送但为确认的分组,等待确认反馈
收到确认反馈后窗口便会向前滑动继续发送新的分组,这里有个原则就是分组是累计确认的,这主要是由于反馈可能是乱序的,为了提高效率,发送方和接收方约定了只会反馈正确收到的最大分组序号。所以假如发送方发送了1-100号分组,当收到1、2、88反馈时,即可判定88号以前的分组均已确认,窗口可以滑动到89了
同时为了简化模型,发送方当收到一个失败反馈时,会将窗口回退到该位置继续发送,即如果已发送的1-100分组中,收到了2号分组的失败确认,则会将窗口回退到2号位置,继续重新发送,这也是因为接收方也是按序接收的,不会在未收到8号之前,接收8之后的分组
选择重传
选择重传是对回退N步策略的一种改进,发送方和接收方都会缓存一些数据,允许乱序确认。即发送方当收到2号出错时,窗口并不回退,而是单独处理2号,同时接收方在收到乱序到达的分组后不会丢失不连续的,而是暂存起来。这样虽然增加了实现难度,但却大大提高了效率
到这里,TCP是如何在不可靠的网络上实现可靠传输的方法应该有一个感性的认识了吧
TCP连接管理
那么TCP的发送方和接收方之间是如何建立和关闭连接的呢?我们常说的三次握手和四次挥手是什么意思呢?
建立连接 三次握手
tcp_three_handshake.png- 终端发送SYN字段为1的特殊分组,请求建立连接
- 服务器确认收到连接建立请求,并开辟所需的变量和缓冲区,返回确认分组,一次握手
- 终端收到确认分组,然后准备变量和缓冲区,返回确认分组,二次握手
- 服务器收到确认请求,三次握手
这里要插一嘴,就是一些坏分子会利用第二步攻击服务器,即只发送连接建立请求,然后服务器准备资源等待后续时终止发送,达到服务器空转的目的。则就是SYN洪泛攻击
关闭连接 四次挥手
tcp_four_goodbye.png- 终端发送FIN字段为1的特殊分组,请求关闭连接,一次挥手
- 服务器返回确认分组,开始清理变量、缓冲区,二次挥手
- 服务器清理完毕,发送FIN字段为1分组,通知终端可以关闭,三次挥手
- 终端返回确认分组,开始清理,四次挥手
TCP拥塞控制
TCP的拥塞控制主要是面向整个互联网的,因为它的主要作用便是根据当前网络环境遏制自己的发送速度。这里我们只需要了解几个简单的概念即可
慢启动
即发送方在发送数据时首先发送1个分组进行试探,成功后继续发送2个,然后依次类推。当然不会这么一直翻倍下去,而是当达到某个阈值后,变化为线性速度增加
加性增,乘性减
在线性增加过程中,若遇到拥塞,窗口大小按照几何倍率减小,重新开始慢启动过程
快速恢复
当在慢启动阶段收到多个冗余确认反馈时,会触发快速恢复事件,发送窗口重新进入加性增阶段
所以一个典型的TCP发送模型大概如下图
tcp_speed_demo.png
网友评论