传输层_TCP&UDP

应用层中调用write/send``recv/read这些系统接口,并没有将数据发送到网络中,而是向下交付到传输层协议,具体什么时候发送数据,由传输层根据一些策略进行数据的实际发送。

传输层的主要功能就是负责 数据的传输,包括如果数据丢失,重复,乱序,发送太快太慢等等一些数据传输可靠性问题。传输层就是根据用户的要求从而解决数据传输的问题。传输层的协议主要由TCP和UDP两种协议。TCP协议是可靠传输的,如果用户想要更可靠的传输就用TCP协议;如果用户追求效率,那么可以使用UDP协议,它是不可靠的,没有面向连接的,因此速度会比TCP协议快一些。

一.UDP

1.1 UDP协议格式

由于UDP报头是固定8字节的,所以根据16位UDP长度与8字节,可以知道当前UDP报文中有效载荷的大小,因此不会出现有效载荷没有读完的情况。当把有效载荷读完后,UDP协议根据报头中的16位目的端口号,将有效载荷中的数据交付给上层应用程序。

由于传输层属于操作系统层,而UDP在内核中是一个结构体,在底层传输不需要序列化与反序列化,因为在所有操作系统中,都强制规定了协议结构体的报头大小位8字节,不用考虑内存对齐了。

1.2 特点
  1. 无连接:知道对端的端口号即可通信,不用考虑对方在不在。
  2. 不可靠:没有确认机制,没有重传机制
  3. 面向数据报:应用层交给UDP多长的报文,UDP原样发送和接收。这种方式不够灵活,但简单。
1.3 UDP缓冲区
  1. UDP没有真正意义上的发送缓冲区,调用sendto会直接交给内核,由内核将数据传给网络层协议后,进行后续传输。
  2. UDP具有接收缓冲区,但这个缓冲区不能保证收到的UDP报的顺序和发送的一致,如果缓冲区满了,再到达的UDP数据就会被丢弃。
  3. 使用UDP发送数据,一次最多只能发送64KB,超过该容量,用户只能自己分片。

二.TCP

2.1 TCP协议格式
  • 4位首部长度:以4字节位单位,标识TCP报头的大小在20-60字节之间。根据这个字段,可以将TCP有效载荷与报头分离
  • 32位序号、32位确认序号:TCP会给报文一个序号,这个序号能保证在TCP接收报文时,报文不会重复、不会丢失、接收顺序不会乱。32位确认序号就是对端告诉接收方,我接收到了确认序号之前的所有报文,你下次发送的报文序号应该从确认序号开始。
  • 16位窗口大小:里面指明了自己接收缓冲区的剩余容量,防止对端发送消息过快/过慢,这种机制就是流量控制。
  • URG:紧急指针标识位,标识该报文中有紧急数据
  • ACK:标识该报文是一个应答报文
  • PSH:催促对端快速处理缓冲区中的数据,让缓冲区的数据处于就绪状态
  • RST:当客户端与服务器进行连接协商时,如果客户端认为连接建立成功,服务端连接失败。如果此时客户端发送消息,但是服务端因为没有连接,所以导致双方连接状态不一样,此时服务器就会给客户端发送一个RST报文,让客户端端重新建立连接
  • SYN:标识该报文是在请求连接
  • FIN:标识该报文是在请求断开连接
  • 上面六位标志是为了区分不同种类的报文,对于每一种报文有其处理方式,并且多个标志可以同时设置。
  • 紧急指针(带外数据):填入紧急数据(1字节)在缓冲区中的偏移量,可以通过recv第四个参数flags设置为MSG__OOB
2.2 TCP可靠性

如果要理解TCP的可靠性,那么我们就要明白什么时候是不可靠的。比如丢包(大量,少量)、重复、乱序、发送太快/太慢,这些都是不可靠的表现。那么TCP是如何知道自己发送的报文丢了呢?这就要引入TCP的确认应答机制了,如果在一个时间段内没有收到应答报文,那么TCP就会认为自己的报文丢失了,然后重新发送报文。

TCP的报文按照顺序发送,但因为网络原因,它们有可能是乱序到达的,如果要保证可靠性,TCP就要给每个报文一个序号,这个序号既可以让报文有序接收,又可以防止报文重复的情况发生。

  • 确认序号X:x-1之前的报文收到了,下次请从x开始发送。这样可以更细粒度的找到丢包原因,允许少量应答报文丢失

TCP可靠性机制:

  1. 确认应答(ACK)机制
  2. 超时重传

TCP为了保证无论在任何环境下都能比较高性能的通信,会动态计算等待的时间,Linux中,超时是以500ms为单位进行控制的,每次判定重传的时间都为500ms的整数倍。如果重发一次后,仍然得不到应答,等待2500ms后再进行重传。如果仍然得不到应答,等待4500ms,以此类推。如果在经过一定次数等待后,仍然收不到应答,那么TCP认为网络/对端主机出现异常,强制关闭连接。

  1. 连接管理机制

在双发主机通信时,双发TCP要经过三次握手建立连接,当通信结束时,双方TCP要经过四次挥手断开连接。

连接在操作系统就是一种数据结构,维护这个连接是要消耗系统资源的。
三次握手和四次挥手:

建立连接的过程是TCP自动完成的,即OS自动完成的,我们上层调用的connect()是发起连接,然后阻塞等待连接完成获取连接,accpet() 是默认阻塞等待连接完成,获取连接。

三次握手是判断双方通信信道流通的最小成本。当三次握手中,前两个报文丢失,那么客户端会触发超时重传,如果第三个报文丢失,那么客户端与服务器对于连接的状态认知不一样,服务器会向客户端发送连接重置报文(RST)。三次握手实际上是包含4个报文,但是为了双方尽快建立连接,所以TCP将中间两个报文使用捎带应答的机制合并在一起。

四次挥手由断开连接的一方发送FIN报文,然后另一方发送ACK报文同意断开连接,但是有可能此时被断开连接的一方还要发送一些数据,等发完数据之后再给对端发送FIN报文请求断开连接。所以没有将FIN和ACK组合在一起。

  • 状态变化:
    • FIN_WAIT1:
    • FIN_WAIT2:
    • CLOSE_WAIT:一方收到FIN报文后会进入CLOSE_WAIT状态,这种状态如果不调用close关闭连接,那么会一直保持这种状态
    • LASK_ACK:被动断开连接的一方当发送FIN报文后处于的状态
    • TIME_WAIT:主动断开连接的一方等待2个MSL时间,确认等到报文被对方收到,防止下次建立连接时产生影响。在处于TIME_WAIT状态时,由于端口号被连接占用,所以导致再次启动程序时,就会报band error错误。但是对于服务器来说,这种情况是不允许发生的,我们可以设置服务器忽略TIME_WAIT状态,直接重启服务。
      • setsockopt(int sockfd, int level, int optname, const void* optval, socklen_t optlen)
        • sockfd:目标套接字
        • level:哪一层,通常填写SOL_SOCKET
        • optname:属性名,SO_REUSEADDR|SO_REUSEPORT
        • optval:填入整型变量的地址,这个变量存1
        • socklen_t:optval的实际长度
  1. 流量控制

双方通信时,会将自己接收能力设置到窗口大小中,双方就可以根据对方接收的能力选择发送报文的速度。当自己的接收缓冲区满时,就会将窗口大小设置为0,这时发送方不在发送数据,而是定期发送探测窗口,询问对方接收能力。同时如果接收方的缓冲区有空间时,接收方也会向对方发送一个窗口更新通知

  1. 拥塞控制

在发送数据时,如果出现少量丢包问题,则会触发超时重传机制。但是如果出现大量丢包,就可能是网络出现故障(网络拥塞),此时TCP就会触发慢启动机制,先减少发送量,探明网络拥塞情况,在不会加重网络拥塞的情况下,逐步增加发送量,以让网络尽快恢复正常。

  1. 拥塞窗口:衡量网络健康状态的指标

网络的状态是一直变化的,所以拥塞窗口也是一直变化的。发送开始时候,拥塞窗口大小为1,每一次收到ACK,拥塞窗口按指数级别增长。每次发送数据时,滑动窗口大小取拥塞窗口和对端接收能力的较小值。当拥塞窗口的大小超过一个阈值(ssthresh)时,按照线性增长,当发生网络拥塞时,重新设置拥塞窗口大小,阈值变为上一次探测的拥塞窗口大小的一半。

  1. 校验和&序列号

TCP效率问题:

  1. 滑动窗口

双方主机在通信时,如果收报文和发报文的顺序是串行的,那么必然通信效率不高。此时TCP引入了滑动窗口,使得在一个窗口内的数据可以并行发送。

)

那么滑动窗口是什么呢?我们知道TCP的发送缓冲区是以字节为单位的,可以看作一个大数组,滑动窗口就是这个数组里的一个子数组,数组下标即为序号。滑动窗口将发送缓冲区划分为三部分:已经收到应答的数据,可以直接发送没有收到应答,不能发送的数据区域。上层将数据放到尚未发送的区域,TCP从可以发送区域中取数据,这种模式就是生产消费模式。

滑动窗口的大小取决于网络拥塞情况和对方的接收能力(16位窗口大小),它的大小是动态变化的。当收到了X序号的应答后,滑动窗口可以向右移动到X位置处。

  1. 快重传(高速重发控制)

当发送端连续收到三个相同的确认序号时,就说明该报文已经丢失,立即触发快重传机制。快重传机制和超时重传机制会同时使用,当不满足快重传触发条件时,就会触发超时重传机制。快重传决定数据传输效率上限,而超时重传决定数据传输效率下限。

  1. 延迟应答

当接收到一个报文后,接收方等一会儿,等上层用户把数据处理一部分,以告诉对方更大的窗口大小,那么对方的滑动窗口就有可能更大,发送的数据可能会更多,借此增加了通信效率。

  • 不是所有包都延迟应答,一般每隔N个包就延迟应答一次或者超过最大延迟时间就应答一次。在不同系统中策略不同
  1. 捎带应答

在延迟应答的基础上, 我们发现, 很多情况下, 客户端服务器在应用层也是 "一发一收" 的. 意味着客户端给服务器说了 "How are you", 服务器也会给客户端回一个 "Fine, thank you";那么这个时候ACK就可以搭顺风车, 和服务器回应的 "Fine, thank you" 一起回给客户端 。

2.4 基于TCP协议的应用层协议
  • HTTP
  • HTTPS
  • SSH
  • Telnet
  • FTP
  • SMTP
相关推荐
千天夜4 分钟前
使用UDP协议传输视频流!(分片、缓存)
python·网络协议·udp·视频流
长弓三石1 小时前
鸿蒙网络编程系列44-仓颉版HttpRequest上传文件示例
前端·网络·华为·harmonyos·鸿蒙
xianwu5431 小时前
反向代理模块
linux·开发语言·网络·git
follycat1 小时前
[极客大挑战 2019]HTTP 1
网络·网络协议·http·网络安全
xiaoxiongip6662 小时前
HTTP 和 HTTPS
网络·爬虫·网络协议·tcp/ip·http·https·ip
JaneJiazhao2 小时前
HTTPSOK:智能SSL证书管理的新选择
网络·网络协议·ssl
CXDNW2 小时前
【网络面试篇】HTTP(2)(笔记)——http、https、http1.1、http2.0
网络·笔记·http·面试·https·http2.0
无所谓จุ๊บ3 小时前
树莓派开发相关知识十 -小试服务器
服务器·网络·树莓派
道法自然04023 小时前
Ethernet 系列(8)-- 基础学习::ARP
网络·学习·智能路由器
EasyCVR4 小时前
萤石设备视频接入平台EasyCVR多品牌摄像机视频平台海康ehome平台(ISUP)接入EasyCVR不在线如何排查?
运维·服务器·网络·人工智能·ffmpeg·音视频