概况
?上篇文章简单描述了一下网络分层。这篇文章就分享一些TCP和UDP的一些内容,这篇文章会分享一些我觉得跟我们开发有直接关联的一些知识。文章内容分为两分部。 ?第一部分是 TCP的那些事 ?第二部分是 UDP的那些事
TCP的那些事
?TCP的内容很复杂,这里只是概述性的讲解它的优缺点,并不会详细描述它的各种算法,策略等。 ?TCP是成熟可靠的协议,它具有以下的功能。
? 1 保证网络包的顺序: ??TCP是受过seq序号来保证网络包的顺序问题的,TCP提供有序的传输,所以每个数据段都要标上一个序号。当接收方收到乱序的包时,有了这个序号就可以重新排序
? 2 防止网络包丢失:
? ?重传数据包是TCP最基本的错误恢复特性之一,它被设计用来对付数据包丢失。
? ?数据包丢失可能有很多原因,包括出故障的应用程序,流量负载沉重的路由器,或者临时型的服务中断。数据包层次上的移动速度非常快,而且数据包丢失通常是暂时的,因此TCP能否检测到数据包丢失并从中恢复显得至关重要。
? ?下面是TCP两种重要的重传策略
超时重传 ? 对发送方来说,当发出去的包不想往常一样得到确认了。当等待一段时间后,还是迟迟收不到,就认为这个包已经丢失了,只能重传了。这个过程称为超时重传。 ? 从发出原始包到重传该包的这段时间 称为RTO
快速重传 ? 当接收方收到一个预料之外的序号时,它假设有一个数据包在传输中丢失了。为了正确地重组数据,接收方必须要得到丢失的数据包,因此它重新发送一个包含丢失数据包序号的ACK数据包,告诉发送方,我还没接收相对应序号的包 ? 当传输主机收到3个来自接收方的重复ACK时,它假设这个数据包确实在传输中丢失了,并立刻发送一个快速重传 ? 因为TCP是通过发送ACK包来 预测 下一次 接收 的包的seq,如果下次 接收的包的seq 是非预期中的,那么tcp会怀疑该包是否丢失了
? 3 流量控制,拥塞控制:
? ?Window又叫Advertised-Window,也就是著名的滑动窗口(Sliding Window),用于解决流控的。
? 滑动窗口机制 ? ? 滑动窗口机制,用于检测何时发生了数据包丢失,并调整数据传输率加以避免。滑动窗口机制利用数据接收方的接收窗口来控制数据流。
? ? tcp通过ack包来声明己方的接收窗口,tcp发送端通过对端的接收窗口 来调整自己的发送窗口。
? ? 发送窗口的大小对性能的影响非常重要,发送窗口可以决定一次过可以发送多少字节,单位是MSS(单个TCP包最大能携带的字节)。在没有拥塞时,发送窗口越大,性能越好。所以在带宽没有限制的条件下,应该尽量增大接收窗口
? ? 比如客户端正在向接收窗口大小位5000字节的服务器发送数据,客户端发送了2500字节,将服务器的缓冲空间减少到2500字节,然后再发送2000字节,进而将缓冲区减少到500字节。然后服务器发送出这些数据的确认,处理缓冲区的数据,得到可用的空缓冲区。该过程会不断的重复
? ?当一台繁忙的服务器 处理来自多个客户端的数据包时,服务器可能会缓慢地清空缓冲区,腾不出空间来接受新数据。如果没有流量控制,这将导致数据包丢失和数据损坏。幸好,当服务器太繁忙,以至不能以接收窗口宣告的速率处理数据时,它可以调整接收窗口的大小。它通过减少发送返回ACK数据包的TCP头部窗口大小值,达到这个目的
? ? 我们知道,发送窗口是收对端的接收窗口 与 网络因素影响。
? 接收窗口 我们都知道,只需要 在 接收方ack 包中 指定接收窗口即可。但是网络因素呢? ? ? 我们在 发送方维护 一个虚拟的拥塞窗口。网络对发送窗口的限制,就是通过拥塞窗口实现的。 ?? 当连接刚刚建立的时候,发送方对网络状况一无所知。如果一口气发太多数据就可能遭遇拥塞,所以发送方把拥塞窗口的初始值定得很小。RFC的建议是2个,3个MSS ? ? 如果发送发出去的包都得到确认,表明还没有达到拥塞点,可以增大拥塞窗口,这个阶段 触碰到拥晒点的概率比较小,所以拥塞窗口继续增大。这个过程叫做慢启动过程。 ? ? 当然并不是一直都以这个速率增大拥塞窗口。当将拥塞窗口比较大的时候,会减慢 拥塞窗口的增加速率
问题一:什么因素造成TCP拆包和粘包的问题: ?为了能够解析清楚这个问题,我要讲解几个内容作为铺垫。
MTU 最大传输单元和 MSS 最大分段大小: ? MTU(Maxitum Transmission Unit) 是链路层一次最大传输数据的大小。MTU 一般来说大小为 1500 byte。MSS(Maximum Segement Size) 是指 TCP 最大报文段长度,它是传输层一次发送最大数据的大小。
IP分片:
? ? 数据包分片是将一个数据流分为更小的片段,是IP用于解决跨越不同类型网络时可靠传输的一个特性。
? ?一个数据包的分片主要基于第二层数据链路协议所使用的最大传输单元(MTU)的大小,以及使用这些第二层协议的设备配置情况。在多数情况下,第2层所使用的数据链路协议是以太网。以太网的默认MTU是1500,也就是说,以太网的网络上所能传输的最大数据包大小是1500字节(并不包括14字节的以太网本身)
? ?当一个设备准备传输一个IP数据包时,它将会比较这个数据包的大小,以及将要把这个数据包传送出去的网络接口MTU,用于决定是否需要将这个数据包分片。如果数据包的大小大于MTU,那么这个数据包就会被分片。
Nagle 算法:
? ?在发出去的数据还没有被确认之前,假如又有小数据生成,那就把小数据收集起来,凑满一个MSS或等收到确认后在发送。
? ?Nagle 算法并没有直接提高性能,它只是减少了部分确认包,减轻了网络负担
网络包的发送流程
? ?首先,应用程序调用 socket API 发送网络包
? ?由于这是一个系统调用,所以会陷入内核态的套接字层中。套接字层会把数据包放到socket发送缓冲区中。
? ?接下来,网络协议栈从socket发送缓冲区中,取出数据包;再按照TCP/IP栈,从上到下逐层处理。然后放到发送队列中。这一切完成后,会有软中断通知驱动程序:发包队列中有新的网络帧需要发送
? ?最后,驱动程序通过DMA,从发包队列中读出网络帧,并通过物理网卡把它发送出去
? ?所以 网速包发送 流程是
? ? socket发送缓冲区 --> 发包队列 --> 物理网卡 发送出去
问题一答案:
? ?如上图和铺垫的知识,影响拆包和粘包的有 socket缓冲区,MTU大小,MSS大小以及如Nagle等的算法。
? ?比如我们应用层发送一串字符串,我们可能首先会理所当然的认为,这个一串字符串会打成一个包发送出去,其实不然,TCP发送和接收数据放在我们的应用层面来讲,其实是一个流(stream),数据会不断的发送和接收,边界更多的是应用层上去处理。
? ?我们所说的包更像是面向流的每次发送,如我要发送1000字节数据,分成10次发送,每次100字节,那么我们说的包,更像是一个个的100字节。只不过有时候应用程序会将包组织起来,让用户看到好像是只有一个数据包一样。
? 拆包和粘包的原因:
? ?1 要发送的数据大于socket缓冲区剩余空间大小,将会发生拆包
? ?2 待发送的数据大于MSS,TCP在传输前将进行拆包
? ?3 诸如Nagle的算法,把小数据收集起来,凑满一个MSS或等收到确认后在发送 是一个粘包的动作
? ?4 一般来说TCP会让MSS = MTU - IP 首部 - TCP首部,也就是说,TCP会尽量不让数据包在IP层分片。
UDP的那些事
? ?UDP相对TCP来说,简单很多,它是面向无连接的。因为它的设计简单,想复杂起来都没办法。在UDP协议头中,只有端口号,包长度和校验码等少量信息,总共就8个字节。
? ?UDP协议有以下特点:
? ?1 UDP协议头长度还不到TCP头的一半,所以在同样大小的包里,UDP包携带的净数据比TCP包多一些
? ?2 UDP没有Seq号和Ack号,无法维持一个连接,所以省去建立连接的负担
? ?3 UDP没有流量控制算法和策略,应用让它发,它就发。
? ?4 UDP不保证不丢失,不保证按顺序到达
?
? ?虽然上面,列举了一些UDP的缺点,但是这些缺点可以按需在应用层上解决,比如QUIC协议,是Google提出的一种基于UDP改进的通信协议,其目的是降低网络通信的延迟,提供更好的用户互动体验。QUIC 会在应用层上,会自己实现快速连接建立,减少重传时延,自适应拥塞控制,是应用层上解决UDP的缺点的代表。
UDP的使用场景:
? ?1 需要资源少,在网络情况比较好的内网,或则对于丢包不敏感的应用,如物联网系统
? ?2 不需要一对一沟通,建立连接,而是可以广播的应用,如 DHCP和VXLAN等协议
? ?3 一些如直播等流媒体,需要处理速度快,时延低,可以容忍少数丢包。
问题一:为什么我们公司物联网项目,使用UDP协议传输时,会将整包大小设置在1500字节以内?
答:
?UDP不像TCP一样在乎双方MTU的大小。它拿到应用层的数据之后,直接打上UDP头就交给下一层了。那么超过MTU的时候怎么办?
?在这种情况下,发送方的网络层负责分片,接收方收到分片后再组装起来,这个过程会消耗资源,降低性能。
?所以我们会将整包大小设置在1500字节以内,尽量的减少网络层分片。
参考资源:
?极客时间趣谈网络协议
?Wireshark 数据包分析实战(第二版)
?Wireshark网络分析就这么简单
|