Linux网络通信:传输层的典型协议UDP协议和TCP协议

前言

Linux网络通信环境中的传输层主要负责应用程序之间的数据传输,传输层有两个典型的协议:UDP协议和TCP协议。

协议的特性影响着上层程序的编写,而协议的特性又来源于协议的实现,我们下面就来深入挖掘UDP协议和TCP协议。

一:UDP协议

UDP协议(User Datagram Protocol):称为用户数据报协议,是OSI参考模型中的一种无连接的传输层通信协议。

1.1 UDP协议格式

UDP 报文分为 UDP 报头和 UDP 数据区两部分。报头由 4 个 16 位长(2 字节)的字段组成,分别说明该报文的源端口、目的端口、报文长度和校验值。
在这里插入图片描述
源端口: 包含发送数据报的应用程序所使用的 UDP 端口,目的端的应用程序利用这个字段的值作为发送响应的目的地址。占据 UDP 报头的前 16 位。

目的端口: 包含接收端应用程序使用的 UDP 端口。

报文长度: 表示 UDP 数据报长度,包含 UDP 报头和 UDP 数据长度,UDP 报文头长度是 8 个字节,所以报文长度最小为 8。

校验值: 使用二进制反码求和算法,检验数据在传输过程中是否被损坏。

二进制反码求和算法:发送端对报文每个字节进行取反相加(sum+=操作),高出16位则截断高位,与低16位继续相加,得到校验值。将校验值填充校验值字段中,封装报头进行发送,接收端接收后继续进行二进制反码求和,如果结果为0则数据传输准确,若非0则数据传输错误丢弃数据。

1.2 UDP协议特点
  1. 传输特点: 无连接、不可靠、面向数据报

使用UDP协议进行网络通信时源端与对端之间不需要建立连接,知道对端的IP和端口号就直接进行传输,但是没有确认机制, 没有重传机制,UDP协议层也不会给应用层返回任何错误信息,不确保数据会被对方安全有序完整的收到(类似于写信),UDP通信还有不提供数据包分组、组装和不能对数据包进行排序的缺点。

面向数据报: 有最大长度限制的传输方式,并且UDP报头中已经确定了UDP报文长度,应用层交给UDP多长的报文,UDP原样发送,既不会拆分,也不会合并。不能够灵活的控制读写数据的次数和数量。所以recvfrom给予的缓冲区也要足够大。但UDP对上层数据的边界比较敏感,每次能交付完整的数据。

因此就需要程序员需要在应用层进行分包操作、包序管理(在应用层的协议头部中,标记数据包的序号,对端接收数据之后,在应用层进行管理),确保数据的有序传输。

  1. 应用场景: 数据传输实时性要求高,而可靠性要求不高的程序(视频传输 )

正因为UDP协议的控制选项较少,在数据传输过程中延迟小、数据传输效率高,适合对可靠性要求不高的应用程序,或可以保障可靠性的应用程序,如:53(DNS)、69(TFTP)、161(SNMP)。

二:TCP协议

TCP协议(Transmission Control Protocol):称为传输控制协议,是一种面向连接的、可靠的、基于字节流的传输层通信协议。

2.1 TCP协议格式

TCP 报文是 TCP 层传输的数据单元,也称为报文段。
在这里插入图片描述
源端口: 包含发送报文的应用程序所使用的 TCP 端口。

目的端口: 包含接收端应用程序使用的 TCP 端口。

序列号: 表示报文段所发送数据的第一个字节的编号。在 TCP 连接中,所传送的字节流的每一个字节都会按顺序编号。

确认号: 表示接收方期望收到发送方下一个报文段的第一个字节数据的编号

头部长度: 确定 TCP 数据段头部分的长度,告诉接收端的应用程序,数据从何处开始。

保留: 为 TCP 将来的发展预留空间,目前必须全部为 0。

URG: 表示本报文段中发送的数据是否包含紧急数据(URG=1后面的紧急指针字段才有效)。

ACK: 表示前面的确认号字段是否有效(ACK=1 时表示有效),连接建立后,ACK必须为 1。

PSH: 对方收到该报文段后是否立即把数据推送给上层(PSH=1 时表示立即推送而不是缓存)。

RST: 表示是否重置连接(RST=1 时说明 TCP 连接出现了严重错误,应重置连接)。

SYN: 建立连接时使用(SYN=1,ACK=0 时表示这是一个请求建立连接的报文段)。

FIN: 标记数据是否发送完毕(FIN=1 时表示数据已经发送完成,可以释放连接)。

窗口大小: 表示当前接收端的接收窗口还有多少剩余空间,用于 TCP 的流量控制。

校验和: 用于确认传输的数据是否有损坏。

紧急指针: 指出本数据段中为紧急数据的字节数,所有紧急数据处理完后,TCP 就会告诉应用程序恢复到正常操作。即使当前窗口大小为 0,也是可以发送紧急数据的,因为紧急数据无须缓存

选项: 用于协商描述一些信息(0~40位)。

2.2 TCP协议特点
  1. 面向连接

使用TCP协议进行网络通信时源端与对端之间需要建立连接,TCP有三次握手建立连接和四次挥手断开连接来进行自己的连接管理,保证双方都具有数据收发的能力。

TCP的三次握手建立连接:

客户端发送SYN连接请求后,等待服务端回答SYN+ACK,并最终对客户端的SYN进行ACK确认。
在这里插入图片描述
为什么握手是三次: 两次不安全,四次没必要。TCP通信需要确保双方都具有数据收发的能力,客户端有可能在发送完SYN之后退出,因此双方都要发送SYN来确保对方具有通信的能力,并且减少资源的浪费。

三次握手失败,服务端怎么处理: 1. 没有收到SYN什么都不做,2. 服务端回复了SYN、ACK,但长时间没有收到客户端ACK确认,则超时后发送RST重置连接报文,释放资源。

TCP的四次挥手断开连接:
在这里插入图片描述
为什么挥手是四次: 发送连接释放报文只能说明本端不再发送数据,而不能保证本端不接收数据,因此被动关闭方在ACK回复之后有可能还会继续发送数据,直到数据发送完成才会发送连接释放报文,因此被动关闭方的FIN和ACK必须分开发送。

TIME_WAIT: 时间等待状态。这段时间是为了避免如果主动关闭连接方最后一次ACK确认丢失,造成被动方没有收到ACK确认,超时就会重传被动关闭方最后一次连接释放报文而产生不可预估的后果。

时间等待状态的持续时间: 2×MSL时间,MSL(报文最大生命周期),重传FIN最大存在MSL,ACK确认最大存在MSL,为了能够处理重传的释放连接请求。并且还会等待所有的报文都消失在网络中,避免对新的应用程序产生影响。

一台主机上出现大量的TIME_WAIT: 表示这台主机上有大量的应用程序主动关闭了连接,常见于一些爬虫服务器,我们可以调整TIME_WAIT时间,或者开启地址重用的套接字选项(setsockopt接口中SO REUSEADDR BOOL,允许套接字和一个已经在使用中的地址绑定,防止socket处于TIME_WAIT无法使用相同的地址信息绑定新的套接字)

一台主机上出现大量的CLOSE_WAIT: 表示被动关闭方有可能没有调用close释放资源(没有给主动断开连接方发送FIN),一直等待上层应用处理。

TCP连接管理中的保活机制: TCP通信中若两端长时间没有数据往来(可配置项:7200s),则每隔一段时间(75s)服务端向客户端发送一个保活探测数据报,要求客户端进行回复,若连续多次没有收到客户端响应(9次),则认为连接断开。

通过设置套接字选项setsockopt:SO_KEEPALIVE(开启保活机制),TCP_KEEPIDLE(多久没有数据往来就发送保活探测),TCP_KEEPINTVL(间隔多久发送保活探测),TCP_KEEPCNT(连续几次没收到响应)

  1. 可靠传输

确认应答机制: 发送数据之后,要求对方进行确认回复,通过报头中的序列号与确认号实现。seq为本条数据的起始序号,通信时seq的计算取决于数据已经发送的长度(seq保证数据在缓冲区中的排序,交付有序),ack为对对方数据的确认序号(三次握手中,ack为对方seq+1。实际通信中,ack为对方seq+数据长度。)告诉对方确认序号之前的数据都完整收到。

超时重传机制: 长时间得不到ACK回复,发送端则会重新发送数据。默认200ms左右。

滑动窗口机制: TCP是可以同时发送多个数据传输而不用非要每一条传输都接收ACK才会发送下一条数据,这样大大可以提高性能。但是如果发送数据过快过多,可能会导致丢包,服务端一条都收不到或者只能零零散散接收到一些片段,则会导致客户端大量的重传包文,十分影响效率,因此引入滑动窗口机制。滑动窗口机制依靠协议报文中的窗口大小字段实现流量控制,表示当前接收端的接收窗口还有多少剩余空间,告诉发送端最多可以发送多少数据。1.发送方会维护一个发送窗口,窗口通过后沿序号与前沿序号实现,后沿就是所要发送数据的起始序号,前沿是根据接收方窗口大小计算的结束序号,后沿的移动取决于是否收到数据的确认回复(收到回复,后沿向前移动),前沿的移动却决于接收方响应的窗口大小。发送窗口表示从后沿到前沿最多发送多少数据。2.接收方会维护一个接收窗口,窗口通过后沿序号与前沿序号实现,后沿就是所要接收数据的起始序号,后沿的移动取决于是否收到了后沿的数据,前沿就是根据接收缓冲区剩余空间大小计算得到的接收的数据结束的序号,前沿的移动取决于缓冲区中剩余的空间大小。窗口大小不能大于接收缓冲区的剩余大小,避免数据发送过多,缓冲区超出存储限制而导致的数据丢包。控制发送者的发送速度从而使接收者来得及接收,防止分组丢失的。

滑动窗口机制应对丢包问题: 1.停等协议:得到一条回复才能发送下一条数据。2.回退N步协议:一条数据丢失,则发送端需要将这条数据及以后的数据都进行重传。3.选择重传机制:一条数据丢失,则发送端仅仅针对丢失的数据进行重传。

MSS: TCP通信时一条数据的最大大小,经通信双方协商,取双方MSS中较小的作为双方通信最大数据段大小。

拥塞控制机制: 有时网络不好也会导致发送数据的丢包,拥塞控制其实是进行网络探测,以一种慢启动,快增长的传输方式,根据网络状态来调整发送速度的机制。拥塞控制是作用于网络的,它是防止过多的数据注入到网络中,避免出现网络负载过大而丢包的情况。起初试探网络状况,也就是说由小到大逐渐增加拥塞窗口的大小,当确认网络状况没有问题的时候传输速度才会逐渐以指数级别增长速度继续增长,但是到达一个阈值后停止继续增长。如果传输过程中出现丢包需要重传情况则会将传输速度缩小为原来的一半,并将滑动窗口置回1。

快速重传机制: 发送端连续发送多条数据,若接收端接收的数据并非是后沿数据,则认为有可能数据丢失,首先不会进行后面数据的确认回复,这时会向发送端间隔连续三次后沿数据的重传请求,要求发送端对后沿数据进行重传。发送端连续收到三条同一重传请求,则对这条数据进行重传。快速重传可以一定程度避免超时重传,减少等待时间。连续发送三次重传请求,为了避免因为网络问题导致的数据包延时到达。提高传输的性能。

延迟应答机制: 接收方接收到数据之后,并不立即进行确认回复,如果立即进行确认回复,则接收缓冲区的剩余空间就会变小,窗口也会变小导致传输的吞吐量变小,从而影响传输速度。于是服务端会稍微在此等待片刻再做应答,等待的时间中可能程序在上层已经将数据取出,此时缓冲区数据被取走缓冲区又恢复到无数据状态,也就不用调小窗口大小控制传输速度了,这样可以加大网络吞吐量,提高传输效率。

捎带应答机制: 接收方接收到数据之后进行确认回复,确认回复就是报头中的确认序号实现的的,为了减少空报头占据带宽的影响,则在即将要发送的数据头部中进行上一条数据的确认回复。

  1. 面向字节流

TCP有一个缓冲,当应用程序传送的数据块太长,TCP就可以把它划分短一些再传送。如果应用程序传送的数据块太短 ,TCP也可以等待积累有足够多的字节后再构成报文段发送出去。接收数据也同理。面向连接的,一种有序的以字节为最小传输单元的传输方式。传输接收灵活,减少IO次数,提高性能。但TCP交付的数据并非是一条完整的数据(对上层给予的数据边界不敏感),也有可能是多条数据。

TCP的粘包问题: TCP面向字节流,TCP有可能将多条数据当成一条来处理。TCP报文中虽然有头部长度,但是放入接收缓冲区中的只有数据,无法区分数据条数,并且发送端数据就有可能粘连。(UDP是连报头一起放入接收缓冲区,recvfrom先取出报头,再取出指定长度的数据)

TCP粘包问题的解决: 程序员在应用层进行数据的边界管理。1.每条数据之间以特殊字符进行间隔(可能要进行转义处理,增加处理负担)。2.数据定长传输,固定长度(数据过短会进行补位,影响性能)。3.在应用层协议头部中,定义数据长度(HTTP、TCP)。

HTTP解决粘包问题: 在应用层进行粘包解决,头部中通过Content-Length确定正文长度。

UDP解决粘包问题: 在传输层进行粘包解决,头部定长8个字节,头部中定义数据报长度。所以UDP是不会产生粘包的。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值