网络协议(六)传输层

前面几篇文章中介绍了网络协议中一到三层协议及相关设备,这篇文章再往上进一层来到第四层——传输层。

传输层有两大重要协议:TCP与UDP。全称:传输控制协议(TCP - Transmission Control Protocol),用户数据报协议(UDP - User Datagram Protocol)。

这两个协议通常被用来对比,那么他们有什么相似点与不同点呢?

TCP、UDP的相似与不同

相似点:两个协议都是工作在传输层,在发送数据流程中负责承接来自应用层的数据,进行自己的内部处理后将指定格式的数据传给网络层;在接收数据流程中负责解析网络包的内容,然后将应用数据传给指定端口对应的应用程序。

不同点:

  • tcp是面向连接的,udp是无连接的
  • tcp进行可靠的数据传输,udp的传输是不可靠的

接下来主要针对两者的不同点进行研究。

面向连接

这里的所谓连接是什么呢?

两台计算机之间可能一墙之隔也可能隔着十万八千里,所以这里的连接绝对不是牵一根网线或者搞个什么专线通道将两者连接起来。传输层协议中所谓连接其实是数据传输者两者之间的一个状态记录。

如上图,设备A和设备B之间隔着互联网世界,互联网世界中间有着错综复杂的道路,有山路十八弯,也有柏油路宽敞大道。设备A给设备B发消息后其实是不确定这个消息能不能正常到达设备B的,有可能半路网络不好,载着消息的快递车就会发生堵车、翻车等状况。

而TCP在干的事就是保证当前设备发的消息能够正常到达对端,并能正常收到反馈。

TCP-面向连接
建立连接

TCP相当于一个消息管理员,在和对端设备正常沟通之前会先进行三次握手,保证自己和对端设备能够正常收发消息。然后TCP消息管理员在自己的小本本上记录下来,我和设备B经过了三次握手,可以正常通讯,此时就算是建立了连接。

保持连接

沟通过程中,如果本次建立的连接开启了TCP探活机制的话,在双方长时间没有消息交互时,到达最大空闲时长后,TCP会发送一个探活包给对端,问候一下:“老铁,你还在吗?”,如果老铁回复了,那么空闲计时器重新计时,如果老铁没回复,则等待一段时候继续追问“你还在吗?”,如果连着几次追问,老铁都没有消息回复,那么当前设备和老铁之前建立的连接就已经不可靠了,TCP就断开这个连接。

// 开启TCP探活机制需要手动开启,以下为java代码示例
Socket socket = new Socket("127.0.0.1",6677);
socket.setKeepAlive(true);

TCP探活定时器的定时时长,追问的次数,与每次追问之间的时间间隔,在linux上由以下几个参数控制

[root@iZ2ze3y5fkxbvg0ydam8onZ ipv4]# cd /proc/sys/net/ipv4
# 探活定时器的时长,即最后一次数据交换到发送第一个保活探测包的间隔,linux 默认值为7200秒
[root@iZ2ze3y5fkxbvg0ydam8onZ ipv4]# cat tcp_keepalive_time 
7200

# 发送探活包后,没有收到回复,继续追问的最大次数,linux 默认为9次
[root@iZ2ze3y5fkxbvg0ydam8onZ ipv4]# cat tcp_keepalive_probes 
9

# 发送探活包后,没有收到回复,距下次追问的时间间隔, lunux 默认为75秒
[root@iZ2ze3y5fkxbvg0ydam8onZ ipv4]# cat tcp_keepalive_intvl 
75
断开连接

两台设备如果沟通完了,要断开连接了,此时TCP消息管理员也会和对端的管理员进行四次挥手,完事后在自己的小本本上拿橡皮将这次的连接记录就擦除掉了。

UDP-无连接

再说UDP,UDP的消息管理员干的活就简单多了,直接就成了一个转发者,管它互联网世界啥情况,直接把包丢进去,对端能不能收到我也不管,主打一个无脑转发。

可靠性

传输层的可靠性在于,应用层将数据交给传输层后,你传输层能不能保证将我的消息完整准确的发给对端的传输层。这里多说一嘴,传输层的可靠性仅限于传输层,传输层接完数据给应用层后,应用层是否可靠由应用程序自己控制。

TCP通过各种机制实现了这个可靠性;UDP却是不管这一套的,只管发出去,对方能不能收到不在我的工作范围之内。所以下面要讲的各种可靠性机制都是基于TCP的。

先上一张图,来看看TCP和UDP的数据包长什么样子,都有哪些东西。

可以看到,相比之下UDP的报头比TCP简单了太多。

TCP保证可靠性的机制有

  • 序号和确认应答
  • 超时重传
  • 流量控制
  • 拥塞控制
序号与确认应答

TCP将应用层发来的请求拆成一个个数据包,每个数据包中都有一对序号与确认号,TCP报文发送者称自己的数据包编号为序号,称接收到对方的数据包编号为确认号 。序号值的范围是32位的无符号数,一次请求中数据包的序号是严格递增的,在它增大到2^{32}-1时,便会回绕到0。起始序号是三次握手阶段双方定下的一个随机值,可以预防“TCP序号预测攻击”。

给数据包添加序号有很多好处:

1.不用再担心传输数据包时的乱序交付。互联网中的道路错综复杂,一个TCP连接发的包也不保证都从同一条路上过,有的包可能绕远,晚于发送时间在它之后的包到达。但是因为有序号的存在,接收端能够知道如何按序重装组合这些数据包。

2.丢失的包可以重传。由于TCP传包都是一传一答的,哪个包对端没有收到它会告诉你,有了序号的话,就会很方便定位到是哪个包。

关于确认应答(ACK),举个数据传输的例子来说明

1.发送方给本次连接初始化的序号为1,第一个数据包的报文段有100Byte数据,发给接收方,接收方收到后应答一个序号为1,确认号为101的数据包。确认号的计算规则为:发送过来数据包的序号+报文段字节长度,在这里为1+100。确认号的含义为:我收到了1-100Byte的数据,你该给我传从101Byte开始的数据了。另外说一下,确认包里的序号是没有什么实用含义的,可以忽略它。

2.发送方继续发送第二个包,序号为101,报文段100Byte。接收方接到后返回应答,序号1,确认号201。

(可以看到TCP其实是为每一个字节做了编号,数据包的序号是报文段第一个字节的编号)

累计确认

正常的发送过程就如上面这般这样循环往复,但是每个包都应答太费带宽了,某些情况下可以采取一些取巧的机制避免这么多应答包在网络中传输,这个机制叫做累计确认,假如包1,包2,包3在很短的时间内连续达到了接收方,接收方就只应答一个包3的确认就行了,发送方收到包3的确认后就认为包1,包2也已经成功被对端的TCP收到了。

累计确认还有一个特性,就是只应答连续收到的最大序号的那个包的应答。举个例子,接收方收到了包1,包2,包3,这时候发送了一个包3的应答,去请求发送包4。但是接下来没等到包4,却等来了包6,那么接收方还是会发送一个包3的应答。下一个包7来了仍然发送包3的应答。

发送方如果收到3次对同一个包的确认,就重传最后一个未被确认的包。阈值设为3被证实可以减少乱序包导致的无作用的重传(spurious retransmission)现象。

发送方重传最后一个未被确认的包后,那在它之后的包还用重传吗?毕竟它也没收到那些包的应答。最初的TCP版本就是傻傻的重传之后的所有包,但是这样会产生很多无用功,导致TCP效率变低,后面就加了一个优化功能,叫做选择确认。

选择确认

选择确认(selective acknowledgment,SACK)是TCP的一种可选扩展,SACK选项并不是强制的。仅当双端都支持时才会被使用。Linux 2.4后默认打开。

选择确认打开后,当接收方发送累计确认的包时,除了在头部正常填充确认号外,在报文段还会加上已成功接收的不连续字节的范围。这样,发送方在收到选择确认后,就可以有选择性地重传那些丢失的数据块,而不需要重传整个窗口内的数据。

重复SACK选项(duplicate-SACK option)是SACK的一项扩展,DSACK主要用于指示接收方已经收到了重复的数据块,具体而言,DSACK通过在TCP报文的选项字段中添加DSACK块来表示。该块指定了已经成功接收的重复数据块的范围。发送方收到DSACK后,可以避免对这些已成功接收的重复数据块进行不必要的重传,提高了TCP在面对网络丢包时的性能。

SACK与DSACK有以下两个参数控制,当参数值为1时代表打开。

[root@iZ2ze3y5fkxbvg0ydam8onZ ipv4]# cd /proc/sys/net/ipv4
[root@iZ2ze3y5fkxbvg0ydam8onZ ipv4]# cat tcp_sack 
1
[root@iZ2ze3y5fkxbvg0ydam8onZ ipv4]# cat tcp_dsack 
1
超时重传

TCP在发出一个包后,会启动一个定时器,如果在定时器超时之前收到了ack包,则定时器停止;如果定时器超时了仍没有收到ack包,则会触发超时重传策略,发送方会重新发送这个包。

关于定时器的时长:开始阶段,TCP会为定时器定一个保守的值作为超时上限,每次到达超时时间后,定时器的值则会被设为前一次值的两倍,直到达到特定阈值。

流量控制

TCP使用滑动窗口协议实现流量控制,接收方在“接收窗口”域指出还可接收的字节数量。发送方在没有新的确认包的情况下至多发送“接收窗口”允许的字节数量。接收方可修改“接收窗口”的值。

如下图所示,假设窗口大小为5,TCP根据窗口大小来确定当前哪些包在窗口范围内,窗口范围外的不做发送与确认处理,窗口内左侧有新包确认后,例如包4传来了确认包,则窗口向右滑动,将起始位置调到包5,此时右侧的包9也到了窗口范围内,包9就可以被发送了。

当接收方宣布接收窗口的值为0,发送方停止进一步发送数据,发送方无法发出数据直至收到接收方修改窗口的指示。为避免因随后的修改接收窗口的数据包丢失使连接的双侧进入死锁,发送方在停发数据时会开始一个“保持定时器”(persist timer),当“保持定时器”到期时,TCP发送方尝试恢复发送一个小的ZWP包(Zero Window Probe),期待接收方回复一个带着新的接收窗口大小的确认包。一般ZWP包会设置成3次,如果3次过后还是0的话,有的TCP实现就会发RST把链接断了。

拥塞控制

拥塞控制是发送方根据网络的承载情况,动态调整发送速率,以获取高性能又能避免拥塞崩溃(congestion collapse,网络性能下降几个数量级)。

拥塞控制的手段有以下几种:慢启动、拥塞避免、快速重传、快速恢复。

慢启动:在连接刚开始时,TCP发送方会以较小的窗口大小发送数据,然后逐渐增加发送窗口的大小,直到达到一个阈值。这有助于避免在网络开始时引发拥塞。

拥塞避免:一旦达到慢启动阈值,TCP进入拥塞避免阶段。在这个阶段,发送窗口的增加速度较慢,通过线性增长来避免引发拥塞。

快速重传:参考上面的累计确认概念,当发送者收到某个包的重复确认请求次数到达阈值,假设重复阈值为3,当发送方收到4次相同确认号的数据包确认(第1次收到确认期望序列号,加3次重复的期望序列号确认)时,则可以认为继续发送更高序列号的数据包将会被接受方丢弃,而且会无法有序送达。发送方应该忽略此包超时计时器的等待重发,立即重发这个被重复确认的数据包。

快速恢复:一旦发送方进行了快速重传,就马上进入快速恢复状态。在这个状态下,拥塞窗口大小被减半,发送方继续发送未确认的数据并期望收到新的确认,每收到一个新的确认,拥塞窗口就增加一次。如果发送方在快速恢复状态下收到了重复的确认(DupACKs),它认为网络可能存在拥塞。此时,拥塞窗口会进一步减半,发送方重新进入拥塞避免状态。

校验和

TCP的16位的校验和的计算和检验过程如下:发送者将TCP报文段的头部和数据部分的和计算出来,再对其求反码(一的补码),就得到了校验和,然后将结果装入报文中传输。接收者在收到报文后再按相同的算法计算一次校验和。这里使用的反码使得接收者不用再将校验和字段保存起来后清零,而可以直接将报文段连同校验加总。如果计算结果是全部为一,那么就表示了报文的完整性和正确性。

如果在传输过程中数据包发生了比特错误,那么在接收端计算校验和时就会得到不同的结果,从而发现数据错误。在这种情况下,接收端通常会要求发送端重新传输数据包。

TCP与UDP的使用场景

TCP的使用场景:
  1. 可靠性要求高: TCP提供可靠的、面向连接的通信。如果应用程序对数据的可靠性有较高的要求,例如文件传输、电子邮件、网页浏览等,通常会选择使用TCP。

  2. 流式数据传输: TCP是面向流的协议,适用于需要按顺序传输的数据,如音频和视频流。

  3. 重要性和正确性: 在需要确保数据正确性且顺序不变的应用场景中,TCP是首选。TCP通过序列号和确认机制保证数据的正确传输和顺序交付。

  4. 面向连接: TCP是面向连接的协议,使用三次握手建立连接,确保通信的可靠性。

UDP的使用场景:
  1. 实时性要求高: UDP是面向无连接的协议,不进行连接的建立和维护,因此传输速度较快。适用于实时性要求较高的应用场景,如语音通话、视频会议、在线游戏等。

  2. 简单的请求-响应通信: UDP适用于简单的请求-响应通信模型,其中一个应用向另一个应用发送独立的请求,而接收方通过单一的响应进行回应。

  3. 广播和多播: UDP支持广播和多播通信,适用于需要向多个主机发送相同数据的场景,如实时直播、多人游戏等。

  4. 较少的协议开销: UDP的头部开销相对较小,适用于对协议开销要求较低的应用场景。

总体而言,选择TCP还是UDP取决于应用的具体需求。如果可靠性和数据正确性对应用至关重要,那么TCP是更合适的选择。如果实时性要求高,而且能够容忍一些数据丢失的情况,那么UDP可能更适合。

好了,到这里传输层的常见知识就梳理完了,下一篇文章就继续深入到应用层探究一下最常见的http与https两种协议。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值