【网络基础】传输层
文章目录
- 【网络基础】传输层
- 1、端口号
- 1.1 工具
- 2、UDP协议
- 2.1 协议端格式
- 2.2 UDP特点
- 2.3 传输数据报
- 2.4 缓冲区
- 2.5 基于UDP应用层协议
- 2.6 使用注意事项
- 3、TCP协议
- 3.1 协议段格式
- 3.2 ACK机制
- 3.3 超时重传机制
- 3.4 连接管理机制
- 3.5 滑动窗口
- 3.6 流量控制
- 3.7 拥塞控制
- 拥塞窗口
- 3.8 延迟应答
- 3.9 捎带应答
- 3.10 粘包问题
- 3.11 TCP异常
- 4、TCP/UDP对比
1、端口号
端口号(Port)标识了一个主机上进行通信的不同的应用程序
在TCP/IP协议中, 用 “源IP”, “源端口号”, “目的IP”, “目的端口号”, “协议号” 这样一个五元组来标识一个通信(可以通过 netstat -n查看)
TCP/P或UDP/IP通信中通常采用5个信息来识别一个通信。它们是“源IP地址”、“目标IP地址”、“协议号”、“源端口号”、“目标端口号”。只要其中某一项不同,则被认为是其他通信。
如何确定端口号
在实际进行通信时,要事先确定端口号。确定端口号的方法分为两种:
-
标准既定的端口号(静态方法),它是指每个应用程序都有其指定的端口号。
像HTTP、TELNET、FTP等广为使用的应用协议中所使用的端口号是固定的。这些端口号也被称之为知名端口号(Well—Known Port Number ),0-1023。应用程序应该避免使用知名端口号进行既定目的之外的通信,以免产生冲突。
有些服务器是非常常用的, 为了使用方便, 人们约定一些常用的服务器, 都是用以下这些固定的端口号:
ssh服务器, 使用22端口
ftp服务器, 使用21端口
telnet服务器, 使用23端口
http服务器, 使用80端口
https服务器, 使用443
除知名端口号之外,还有一些端口号也被正式注册,不过,这些端口号可用于任何通信用途。它们分布在1024到49151的数字之间。
-
时序分配法(动态分配法),此时,服务端有必要确定监听端口号,但是接受服务的客户端没必要确定端口号。
在这种方法下,客户端应用程序可以完全不用自己设置端口号,而全权交给操作系統进行分配。操作系统可以为每个应用程序分配互不冲突的端口号。例知,每需要一个新的端口号时,就在之前分配号码的基础上加1。这样,操作系统就可以动态地管理端口号了。
根据这种动态分配端口号的机制,即使是同一个客户端程序发起的多个TCP连接,识别这些通信连接的5部分数字也不会全部相同。动态分配的端口号取值范围在49152到65535之间。
端口号与协议的关系
端口号由其使用的传输层协议决定。因此,不同的传输协议可以使用相同的端口号。例如,TCP与UDP使用同一个端口号,但使用目的各不相同。这是因为端口号上的处理是根据每个传输协议的不同而进行的。
数据到达IP层后,会先检查IP首部中的协议号,再传给相应协议的模块。如果是TCP则传给TCP模块、如果是UDP则传给UDP模块去做端口号的处理。即使是同一个端口号,由于传输协议是各自独立地进行处理,因此相互之间不会受到影响。
1.1 工具
netstat
(Network Statistics)是一个用于检查和显示网络连接、路由表、网络接口统计信息等的命令行工具。它在各种操作系统中都有版本,包括UNIX/Linux、Windows等。netstat
提供了有关系统网络活动的实时或静态信息,使管理员和用户能够监视和诊断网络连接问题。
netstat
命令的基本用法是在命令行中输入 netstat
,后面可以跟随一些选项和参数来获取不同类型的网络信息。以下是一些常见的用法和选项:
netstat -a
:显示所有活动的网络连接和监听端口。netstat -t
:显示TCP协议相关的网络连接信息。netstat -u
:显示UDP协议相关的网络连接信息。netstat -n
:以数字形式显示网络地址和端口号,而不解析为域名和服务名。netstat -r
:显示路由表信息。netstat -i
:显示网络接口统计信息。netstat -p
:显示与每个连接关联的进程信息(需要管理员权限)。
在UNIX/Linux系统中,netstat
命令可能会被一些新的工具和命令替代,如 ss
(Socket Statistics)和 ip
命令。这些工具提供更强大和详细的网络信息,并且通常比传统的 netstat
更快和更准确。
pidof
是一个用于查找正在运行的进程的命令行工具,通常用于返回与指定进程名相关联的一个或多个进程的PID(进程标识符)。这个命令在许多UNIX/Linux系统中都可用,可以通过命令行终端或脚本来使用。
基本语法:
pidof [选项] 进程名
常见选项:
-s
:以单个PID的形式输出结果。如果有多个进程匹配进程名,只返回其中一个PID。-o
:只返回最老的进程PID。-x
:返回与指定进程名完全匹配的PID。
示例:
pidof sshd
:返回与进程名 “sshd” 相关联的一个或多个PID。pidof -s sshd
:返回一个与 “sshd” 相关的PID,如果有多个匹配,只返回其中一个。pidof -o -s sshd
:返回最旧的一个与 “sshd” 相关的PID。
pidof
可以帮助你快速找到正在运行的特定进程的PID,方便进行进程管理和操作。请注意,有时候进程名可能是带有路径的可执行文件名,所以在使用 pidof
时要确保输入的进程名正确匹配目标进程。
2、UDP协议
2.1 协议端格式
UDP(User Datagram Protocol)是一种无连接的、无状态的传输层协议,通常用于在计算机网络上以尽量少的开销进行数据传输。UDP协议段(也称为UDP数据报)的格式如下:
- 源端口号(16位):指示发送方的应用程序使用的端口号。
- 目标端口号(16位):指示接收方的应用程序期望接收的数据的端口号。
- 长度(16位):表示UDP数据报的总长度,包括报头和数据。
- 校验和(16位):提供简单的错误检测,用于验证数据报是否在传输过程中出现了错误。
以下是UDP协议段的简要格式:
需要注意的是,UDP协议不提供像TCP一样的可靠性和流量控制,因为它不支持连接的建立、维护和断开。UDP只是简单地将数据从发送方传输到接收方,并且不会对数据包的顺序或丢失进行处理。这使得UDP非常适合那些对实时性要求高、可以容忍丢失少量数据的应用,例如音频和视频传输、在线游戏等。
2.2 UDP特点
-
无连接性 (Connectionless): UDP协议是无连接的,这意味着发送方不需要事先与接收方建立连接。就像你寄信一样,只要知道收信人的地址,你就可以直接把信寄出去,而不需要预先通知收信人。
-
不可靠性 (Unreliable): UDP不提供数据包的确认机制和重传机制。一旦发送数据,UDP就不会等待接收方的确认信号,也不会重新发送数据包,无论数据包是否成功到达目的地。这就类似于寄信时,寄出后你不会收到寄信局的确认,也不会知道是否邮件丢失。
-
面向数据报 (Datagram-Oriented): UDP以数据报的形式传输数据,每个数据报是独立的、完整的数据单元。这意味着发送方将数据分割成数据报,然后将它们发送到目的地。接收方则根据数据报的边界解析数据。这就类似于你将信件分成小片,寄出后这些小片可能以不同的顺序到达,接收方需要按照标记重新组装信件。
虽然UDP不提供像TCP那样的可靠性和流量控制,但正是因为这些特点,UDP在某些场景下非常有用。它适用于那些对实时性要求高、可以容忍一些数据丢失的应用,例如在线游戏、音频和视频传输,以及一些网络探测工具等。但在需要确保数据完整性和可靠传输的情况下,TCP更适合,因为它提供了连接的建立、数据包确认和重传等机制。
2.3 传输数据报
在UDP协议中,应用层将报文交给UDP的时候,UDP会将报文原样地发送,不会对报文进行拆分或合并。这意味着如果应用层发送100个字节的数据,UDP将会以这100个字节的数据报文进行发送。
接收端需要调用与发送端发送数据时对应次数的recvfrom
来接收数据。如果发送端一次性发送了100个字节,接收端也必须调用一次recvfrom
来接收这100个字节,而不能循环调用多次recvfrom
来尝试接收数据。UDP没有数据流的概念,每次接收都是基于数据报的,因此接收端需要在每次接收时保证正确地处理整个数据报。
这是因为UDP的无连接特性。在无连接协议中,每个数据报都是独立的,没有前后关系,所以接收端需要根据数据报的边界来解析和处理数据。如果需要将应用层的数据划分成更小的块并进行循环接收,你可能需要在应用层自行处理这个分块逻辑,然后分别发送多个UDP数据报。
2.4 缓冲区
-
发送缓冲区和接收缓冲区:UDP确实没有像TCP那样的真正的发送缓冲区,而是将数据直接交给内核,然后内核会将数据传递给网络层协议进行后续的传输动作。另一方面,UDP具有接收缓冲区,用于存储接收到的数据报。但是,与TCP不同,UDP的接收缓冲区不会根据数据报的顺序自动排序,因此在处理接收数据时,应用层需要自行处理数据报的顺序问题。
-
报文顺序和丢失:UDP不保证数据报的顺序和发送顺序一致。这就意味着如果应用层发送了多个UDP数据报,它们在传输过程中可能会以不同的顺序到达接收端。此外,UDP也没有任何机制来确保数据的完整性,因此在网络拥塞或丢包的情况下,UDP数据报可能会丢失。
-
全双工通信:全双工是一个重要概念。UDP套接字是全双工的,这意味着它可以在同一时间进行读取和写入操作。这使得应用程序能够同时发送和接收数据,而不需要切换上下文。全双工通信对于需要实时性和快速数据交换的应用非常有用,例如实时游戏和视频通话等。
2.5 基于UDP应用层协议
-
NFS(Network File System):NFS是一种用于在网络上共享文件系统的协议。它允许计算机通过网络访问远程主机上的文件和目录,就像是本地文件系统一样。NFS常用于UNIX和Linux系统之间共享文件和数据。
-
TFTP(Trivial File Transfer Protocol):TFTP是一种简单的文件传输协议,用于在计算机之间传输文件。与FTP(文件传输协议)相比,TFTP更简单,功能较少,适用于一些场景,如无盘设备的启动过程中的固件传输。
-
DHCP(Dynamic Host Configuration Protocol):DHCP是一种用于自动分配IP地址和其他网络配置信息的协议。当计算机加入网络或者重新连接到网络时,DHCP允许它自动获取IP地址、子网掩码、默认网关、DNS服务器等信息,从而简化了网络配置过程。
-
BOOTP(Bootstrap Protocol):BOOTP是一个用于无盘设备启动的协议。它类似于DHCP,但更早出现,用于为无盘设备(如磁盘less的工作站或终端)分配IP地址等配置信息。
-
DNS(Domain Name System):DNS是一个用于将人类可读的域名(如www.example.com)映射到IP地址的系统。它使得在浏览器中输入域名时,能够找到正确的服务器IP地址,从而实现了互联网上的域名解析。
这些协议在计算机网络中发挥着重要的作用,使得网络通信和配置更加方便和高效。
2.6 使用注意事项
UDP协议头中的长度字段是16位,这意味着一个UDP数据报(包括UDP头部)的最大长度是64K(65535字节)。然而,尽管在某些情况下这可能会被认为是一个相对较小的限制,但UDP的设计初衷并不是用于大量数据的传输,而是注重低延迟和实时性。
当需要传输超过64K的数据时,需要在应用层手动进行分包。这通常涉及将大的数据分割成较小的块,然后逐个发送。接收端需要根据应用层的逻辑来接收和拼装这些分开的数据块,以重新构建完整的数据。
尽管UDP在处理大量数据时需要应用层更多的控制和处理,但在某些情况下它仍然有优势,比如在实时性和速度方面。如果数据完整性和可靠性对于应用非常重要,而且数据量较大,那么考虑使用TCP可能会更合适,因为TCP提供了连接的建立、流量控制、数据确认和重传等机制。
选择UDP还是TCP取决于应用需求,例如是否需要实时性、是否容忍数据丢失以及数据的大小等。
3、TCP协议
3.1 协议段格式
TCP(Transmission Control Protocol)是一种在计算机网络中常用的传输层协议,它负责在通信的两个端点之间提供可靠的、面向连接的数据传输。TCP报文段的格式由多个字段组成,每个字段都有特定的作用。以下是TCP报文段的各个组成部分及其作用:
- 源端口号(Source Port):16位字段,用于标识发送方的端口号。
- 目标端口号(Destination Port):16位字段,用于标识接收方的端口号。
这两个字段一起确定了数据通信的源和目标应用程序。
-
序号(Sequence Number):32位字段,用于标识发送方发送的数据字节在整个数据流中的序列位置。用于实现数据的有序传输。
-
确认号(Acknowledgment Number):32位字段,仅在ACK标志位被设置时有效。表示接收方期望接收的下一个字节的序列号,用于实现可靠的数据传输。
-
数据偏移(Data Offset):4位字段,指示TCP头部的长度,以32位字为单位。由于TCP头部的长度是可变的,这个字段确定了数据部分的起始位置。
-
保留(Reserved):6位字段,保留未来使用,目前置为0。
-
控制位(Flags):TCP头部包含多个标志位,用于控制TCP连接的不同方面,例如:
- URG(Urgent):表示紧急指针字段是否有效。
- ACK(Acknowledgment):表示确认号字段是否有效。
- PSH(Push):表示接收方应尽快将数据交给应用层。
- RST(Reset):用于重置连接。
- SYN(Synchronize):用于建立连接。
- FIN(Finish):用于关闭连接。
-
窗口大小(Window Size):16位字段,表示接收方的可用缓冲区大小,用于流量控制,以确保发送方不会发送过多的数据导致接收方缓冲区溢出。
-
校验和(Checksum):16位字段,用于检测TCP头部和数据部分的错误。通过校验和,接收方可以验证数据在传输过程中是否发生了损坏。
-
紧急指针(Urgent Pointer):16位字段,仅在URG标志位被设置时有效。指示紧急数据的末尾位置,用于实现紧急数据传输。
-
选项(Options):可变长度的字段,包含一些可选的参数,如最大段大小(MSS)、时间戳、窗口缩放因子等。
-
数据(Padding):用于保证TCP头部的长度为32位字的整数倍,以对齐数据。
这些组成部分共同构成了TCP报文段,通过它们,TCP协议实现了可靠的、面向连接的数据传输。
3.2 ACK机制
确认应答(ACK,Acknowledgment)机制是TCP协议中的一个重要特性,用于实现可靠的数据传输。在TCP连接中,接收方通过发送ACK报文段来确认已经正确接收到发送方发送的数据。以下是确认应答机制的工作原理:
-
发送方发送数据:发送方将数据划分为一个个的数据段,每个数据段都会被分配一个序列号。发送方将这些数据段按顺序发送给接收方。
-
接收方接收数据:接收方接收到数据后,会将数据缓存起来,然后发送一个ACK报文段给发送方。ACK报文段中的确认号字段表示接收方期望接收的下一个数据段的序列号。
-
发送方等待确认:发送方在发送数据段后,会等待接收到对应的ACK报文段。如果一段时间内未收到ACK,发送方会认为数据可能已经丢失或损坏,因此会触发超时重传机制,重新发送相应的数据段。
-
接收方去重:接收方可能会收到重复的数据段,或者乱序的数据段。接收方会根据序列号来判断是否是重复数据,并根据序列号将乱序的数据重新排序。然后,接收方只会向上层应用传递正确顺序的数据,避免重复处理。
-
确认号的使用:ACK报文段中的确认号表示接收方期望接收的下一个数据段的序列号。这使得发送方可以知道哪些数据已经被正确接收,从而可以继续发送下一批数据。
-
确认号的累积确认:接收方可以一次性确认多个数据段,只需在ACK报文段中设置确认号为期望接收的下一个数据段的序列号。这样,发送方知道在这个序列号之前的所有数据都已经成功接收。
通过确认应答机制,TCP协议可以保证数据的可靠传输。发送方可以根据接收到的ACK报文段来调整数据发送的速率,而接收方可以确保只有正确的数据被传递给应用程序。这种机制使得TCP在不可靠的网络环境中能够实现高效的数据传输。
TCP将每个字节的数据都进行了编号. 即为序列号
每一个ACK都带有对应的确认序列号, 意思是告诉发送者, 我已经收到了哪些数据; 下一次你从哪里开始发
3.3 超时重传机制
超时重传的超时是指在重发数据之前,等待确认应答到来的那个特定时间间隔。如果超过了这个时间仍然为收到确认应答,发送端将会重发数据。那么这个数据是如何确定的呢?
最理想就是找到一个最小时间,它能保证确认应答一定能在这个时间内返回。但是这个时间长短随着数据包途径的网络环境的不同会有所变化。
TCP要求不论处在何种网络环境下都要提供高性能通信,而且无论网络拥堵的情况发生如何改变,都必须保持这一特性。为此,它在每次发包时都会计算往返时间及其偏差,将这个往返时间和偏差相加重发超时的时间,就是比这个综合要稍微大一点的值。
数据被重发以后若还是收不到应答,就会进行再次发送,此时,等待确认应答的时间将会以2倍,4倍的指数函数延长
不过,数据也不会无限,反复的重发。当达到一定的重发次数之后,如果仍然没有任何确认应答返回,就会判断为网络或对端主机发生异常,强制关闭连接。
3.4 连接管理机制
TCP的三次握手以及TCP的四次挥手!
三次握手: 建立一个TCP连接时,需要客户端和服务端总共发送3个包以确认连接的建立, 在Socket编程中,这一过程由客户端执行connect来触发,具体流程图如下:
- 第一次握手:Client将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给Server, Client进入SYN_SENT状态,等待Server确认。
- 第二次握手:Server收到数据包后由标志位SYN=1知道Client请求建立连接,Server将标志位 SYN和ACK都置为1,ack=J+1,随机产生一个值seq=K,并将该数据包发送给Client以确认连接请求 ,Server进入SYN_RCVD状态。
- 第三次握手:Client收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK 置为1,ack=K+1,并将该数据包发送给Server,Server检查ack是否为K+1,ACK是否为1,如果正确则 连接建立成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client与Server之间可以 开始传输数据了。
四次挥手: 终止TCP连接,就是指断开一个TCP连接时,需要客户端和服务端总共发送4个包以确认连接的断开。 在Socket编程中,这一过程由客户端或服务端任一方执行close来触发,具体流程图如下:
- 第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入 FIN_WAIT_1状态
- 第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同, 一个FIN占用一个序号),Server进入CLOSE_WAIT状态。
- 第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK 状态。
- 第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手。 另外也可能是同时发起主动关闭的情况:
另外还可能有一个常见的问题就是:为什么建立连接是三次握手,而关闭连接却是四次挥手呢? 答:因为服务端在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里 发送给客户端。而关闭连接时,当收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还 能接收数据,己方也未必全部数据都发送给对方了,所以己方可以立即close,也可以发送一些 数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会 分开发送。
TCP状态转移图:
3.5 滑动窗口
每一个发送的数据段, 都要给一个ACK确认应答. 收到ACK后再发送下一个数据段. 这样做有一个比较大的缺点, 性能较差. 尤其是数据往返的时间较长的时候
既然这样一发一收的方式性能较低, 那么我们一次发送多条数据, 就可以大大的提高性能(其实是将多个段的等待时间重叠在一起了)
TCP移动窗口(Sliding Window)是一种流量控制机制,用于在TCP连接中管理发送方和接收方之间的数据流。它允许发送方在不等待每个数据段的确认情况下连续发送多个数据段,从而提高数据传输的效率。
移动窗口的核心思想是,发送方可以发送一定数量的数据段(也称为窗口大小)而无需等待确认,只要这个窗口内的数据都在接收方正常接收。接收方会通过ACK报文段来确认接收到的数据,并更新窗口的大小。这样,发送方可以根据窗口的大小来控制发送数据的速率,避免过快地发送数据导致接收方缓冲区溢出。
TCP移动窗口的一些关键概念和机制:
-
窗口大小(Window Size):窗口大小是一个动态调整的值,表示接收方缓冲区中还可以容纳多少字节的数据。发送方根据窗口大小来决定可以连续发送多少个数据段。
-
发送窗口:发送方的窗口大小,表示可以发送但尚未收到确认的数据的最大大小。发送方只能在发送窗口内发送数据,一旦发送窗口内的数据被确认,窗口将向前滑动。
-
接收窗口:接收方的窗口大小,表示可以缓存但尚未被确认的数据的最大大小。接收方根据已经接收到的数据和缓冲区的剩余空间来调整接收窗口大小。
-
窗口滑动:当发送方收到一定数量的ACK报文段时,表示接收方已经成功接收了一部分数据,此时发送方会将窗口向前滑动,允许发送更多的数据。
-
快速重传:如果发送方连续发送的数据段没有被正确接收(接收方未收到或丢失),接收方会重复发送ACK报文段来请求缺失的数据,从而实现快速重传。
-
窗口调整:接收方可以通过调整窗口大小来告知发送方自己的缓冲区状态。如果接收方的缓冲区较大,窗口大小可以增加,允许发送方发送更多数据。如果接收方的缓冲区较小,窗口大小会减小,限制发送方的数据流量。
通过移动窗口机制,TCP协议可以实现流量控制,使得发送方和接收方之间的数据传输可以根据网络状况和接收方的处理能力进行动态调整,从而实现更高效的数据传输和更好的网络性能。
3.6 流量控制
流量控制(Flow Control)是TCP协议中的一项关键功能,它确保发送端不会过快地发送数据,从而避免接收端的缓冲区溢出、丢包、数据重传以及其他不必要的问题。
TCP的流量控制主要通过使用移动窗口机制来实现。接收端会通过发送窗口大小来告知发送端自己的可用缓冲区空间。发送端根据接收端的窗口大小来调整自己的发送速率,确保不会发送超过接收端缓冲区能力的数据量。
流量控制的工作过程如下:
-
初始阶段:在连接建立时,发送端和接收端会协商初始的窗口大小。这个窗口大小可以根据接收端的缓冲区大小和其他因素来确定。
-
动态调整:随着数据的传输,接收端会根据自己的缓冲区状态动态调整窗口大小。如果接收端的缓冲区越来越满,它会减小窗口大小,通知发送端降低发送速率。
-
发送窗口滑动:一旦接收端确认了已经接收到的数据,它会更新窗口大小,并通过ACK报文段通知发送端。发送端收到ACK后,可以将窗口滑动,允许发送更多的数据。
-
限制发送速率:发送端根据接收端的窗口大小来限制自己的发送速率,确保不会超出接收端的处理能力。
通过流量控制,TCP协议可以在发送和接收之间维持一种动态平衡,以确保数据的稳定传输。这有助于避免网络拥塞、数据丢失以及不必要的重传,从而提供了可靠且高效的数据传输机制。
3.7 拥塞控制
拥塞控制(Congestion Control)是TCP协议中的另一个重要特性,用于在网络中避免过多的数据流量引起的拥塞现象。拥塞控制机制旨在确保网络资源被合理利用,避免数据丢失、延迟增加以及网络性能下降等问题。
拥塞控制的关键目标是在发送端和接收端之间保持一个均衡的数据流,使得网络能够稳定运行,不超过其负荷能力,同时也能最大化地利用网络资源。以下是拥塞控制的一些核心概念和机制:
-
拥塞的原因:拥塞可能发生在网络中的某些路由器、链路或节点负载过重,导致数据包堆积、延迟增加和数据丢失。
-
拥塞检测:拥塞控制需要检测网络是否处于拥塞状态。发送方和接收方可以通过观察数据包的延迟、丢失情况以及ACK报文段的反馈来判断是否发生了拥塞。
-
拥塞信号:当发送方和接收方都观察到网络拥塞的迹象时,会通过特定的拥塞信号来触发拥塞控制机制。例如,发送方可能会减少发送速率。
-
慢启动(Slow Start):拥塞控制的一个阶段,用于在连接初始阶段逐渐增加发送速率。发送方从较小的窗口大小开始,然后每次接收到一个ACK报文段,窗口大小会指数级增加,从而逐渐加快发送速率。
-
拥塞避免:在慢启动阶段之后,发送方会进入拥塞避免阶段。在这个阶段,窗口大小的增长会变得线性,以避免突然增加的数据流量导致拥塞。
-
快重传和快恢复:如果接收方连续收到相同的序列号的ACK报文段,表明网络中的某个数据段可能丢失,发送方会快速重传该数据段,而不是等待超时。快重传通常与快恢复机制一起使用,以便在恢复后适当增加发送速率。
-
超时重传:如果发送方在超时时间内没有收到ACK报文段,会假定数据丢失,并重传相应的数据段。
拥塞窗口
在TCP的拥塞控制机制中,拥塞窗口数量是一个重要的概念,通常称为"CWND"(Congestion Window)。拥塞窗口数量表示在一个拥塞控制周期内可以发送的数据段的最大数量。拥塞窗口的大小会根据网络的拥塞状态进行动态调整,以避免引起网络拥塞。
以下是拥塞窗口数量在不同阶段的变化情况:
-
慢启动阶段(Slow Start):
- 初始阶段,拥塞窗口大小为1个数据段(通常称为MSS,最大段大小)。
- 在每次收到一个确认的ACK报文段后,拥塞窗口大小会翻倍,即指数级增加。
- 该过程会持续,直到拥塞窗口达到慢启动门限(ssthresh)。
-
拥塞避免阶段(Congestion Avoidance):
- 一旦拥塞窗口大小达到慢启动门限(ssthresh),就会进入拥塞避免阶段。
- 在拥塞避免阶段,拥塞窗口大小会逐渐线性增加,而不是指数级增加。
- 拥塞窗口的增长速率较慢,以防止过快增加数据流量引起拥塞。
-
快重传和快恢复机制:
- 如果网络中出现数据丢失,发送方可能会收到连续的重复ACK报文段,表示接收方已经接收到某个数据段之前的所有数据。
- 在这种情况下,发送方会认为某个数据段可能已经丢失,并执行快重传和快恢复机制。
- 拥塞窗口会减半,并设置慢启动门限为当前拥塞窗口大小的一半。
-
动态调整:
- 拥塞窗口的大小会根据接收到的ACK报文段、网络的延迟情况和数据丢失情况动态调整。
- 当网络出现拥塞时,拥塞窗口会减小,以降低发送速率,避免加剧拥塞。
拥塞窗口的动态变化是拥塞控制机制的核心,它可以根据网络的状态来自适应地调整数据的发送速率,以实现稳定的数据传输和避免过度拥塞。
3.8 延迟应答
“延迟应答”(Delayed Acknowledgment)是指在某些情况下,TCP接收方在接收到数据后,不会立即发送确认(ACK)报文段,而是会延迟一段时间才发送确认。这个延迟可以在一定程度上优化网络性能和减少网络负载。
延迟应答的原因和优势包括以下几点:
-
减少ACK报文段数量:如果每接收到一个数据段就立即发送一个ACK报文段,会导致网络中的ACK报文段增多,从而可能造成网络拥塞。通过延迟应答,可以将多个确认合并在一个ACK报文段中,减少了网络上的控制信息。
-
提高带宽利用率:将多个确认合并在一个ACK报文段中可以有效地减少控制信息的开销,从而提高了实际可用带宽的利用率,让更多的带宽用于传输数据。
-
防止不必要的ACK洪水:如果发送端连续发送大量的数据段,接收端可能会为每个数据段都发送一个ACK报文段。这可能会导致接收端发送过多的ACK报文段,浪费网络资源。通过延迟应答,可以避免不必要的ACK洪水。
-
适应延迟较大的网络:在一些高延迟的网络环境中,立即发送ACK可能会导致额外的延迟。通过延迟应答,可以减少ACK报文段的数量,降低了在高延迟网络中的延迟增加。
然而,延迟应答也可能带来一些潜在的问题:
-
数据段丢失的确认延迟:如果数据段丢失,发送方可能需要等待更长的时间才能收到确认,从而触发超时重传机制,影响数据传输的速度和可靠性。
-
流控制的影响:延迟应答可能会影响发送方的流控制机制,使得发送方不能及时了解接收方的可用缓冲区大小。
尽管有一些潜在的问题,TCP延迟应答的优势通常在大部分情况下是明显的。不同的TCP实现可能在延迟应答方面有不同的策略和算法,以在各种网络条件下实现最佳的性能和可靠性平衡。
3.9 捎带应答
“捎带应答”(Piggyback Acknowledgment)是一种优化的TCP确认机制,它允许在发送数据的同时,在数据段中捎带确认信息,从而减少确认报文段的数量,提高网络利用率和性能。
通常情况下,TCP接收方收到数据后会发送确认报文段(ACK),以告知发送方已经成功接收数据。而在捎带应答机制下,接收方会尝试将ACK信息捎带到它自己发送的数据段中,从而在一个数据段中同时包含数据和确认。
这种机制的优势在于:
-
减少ACK报文段数量:通过将ACK与数据段捎带在一起,可以减少网络上的确认报文段数量,从而提高了网络的利用率。
-
优化网络性能:较少的确认报文段可以减少网络的控制信息开销,使得更多的带宽可以用于实际数据传输,从而优化了网络性能。
-
避免ACK洪水:在高速传输环境中,频繁发送ACK报文段可能会导致ACK洪水现象,从而影响网络效率。捎带应答可以一定程度上避免这个问题。
需要注意的是,捎带应答并非在所有情况下都适用。它在以下情况下可能会受到一些限制:
-
延迟敏感的应用:捎带应答可能会引入额外的延迟,因为接收方需要等待合适的时机将ACK捎带在数据段中。
-
小数据段的情况:如果发送的数据段很小,放入ACK可能会使数据段过小,从而增加了网络开销。
-
乱序的数据段:如果数据段在传输过程中发生乱序,可能会导致ACK无法准确与特定数据段捎带,从而引入一些问题。
捎带应答是一个在性能和延迟之间权衡的机制,它可以在适当的情况下提供一种有效的方式来减少网络控制信息的开销。
3.10 粘包问题
粘包问题(Packet Pasting Problem)是在数据通信中常见的一个现象,它指的是在发送数据时,多个数据包(通常是短小的数据包)可能会被合并成一个大的数据包发送,或者一个大的数据包可能会被分割成多个小的数据包发送,从而导致数据在接收端的处理出现混乱或错误。
粘包问题发生的主要原因是因为底层网络协议的不可靠性和数据传输的异步性,导致数据在传输过程中的大小和边界信息可能会丢失或混乱。以下是粘包问题发生的一些典型情况:
-
TCP协议的缓冲区机制:TCP协议为了提高传输效率,会将多个小的数据包合并成一个大的数据包进行传输。这可能导致接收端一次性收到多个数据包,从而引发粘包问题。
-
UDP协议的不可靠性:UDP协议不提供可靠的数据传输,数据包可能在传输过程中被丢失、重复或乱序。这可能导致接收端无法准确地判断数据包的边界。
-
网络拥塞或延迟:网络拥塞或延迟可能导致数据包的传输时间不确定,从而导致数据包在接收端的处理出现混乱。
解决粘包问题的方法包括:
-
消息边界标志(Message Delimiters):在数据包中添加特定的边界标志,例如换行符、特定字符序列等,用于标识数据包的边界。接收端可以根据边界标志来正确分割数据包。
-
固定长度消息(Fixed-Length Messages):将要发送的数据包固定为特定的长度,不足部分用填充字符补齐。接收端可以按照固定长度来正确解析数据包。
-
消息长度前缀(Length Prefix):在每个数据包的前面添加表示数据包长度的前缀。接收端首先读取前缀,然后根据长度读取相应的数据。
-
使用应用层协议:在应用层设计自定义的消息协议,包括数据包的结构、边界标志和长度等信息,使得发送端和接收端可以根据协议正确解析数据。
-
使用流量控制和拥塞控制:TCP协议的流量控制和拥塞控制机制可以一定程度上减轻粘包问题,确保数据逐个传输。
不同情况下适用不同的解决方案,根据具体的应用场景和数据通信需求,选择合适的方法来解决粘包问题。
3.11 TCP异常
情况和处理 TCP 异常:
-
进程终止、机器重启: 当进程终止或机器重启时,TCP 连接会被关闭。正常的关闭过程涉及发送 FIN 报文段,而关闭的一方会发送 ACK 报文段作为确认。这样,另一端收到 ACK 后也会发送自己的 FIN 报文段来完成连接关闭。
-
机器掉电/网线断开: 如果连接的一方在接收到数据后突然掉电或者网络断开,TCP 的另一端可能会一直等待确认,因为没有收到确认报文段。为了处理这种情况,TCP 实现了一个保活定时器,发送探测报文段以确认连接的存活性。如果在一定时间内没有收到回复,连接就会被认为是异常的,并被关闭。此外,如果连接一方确实发送了数据,但另一方没有回应,也会根据超时情况来判断连接是否还存在。
-
应用层协议检测: 像 HTTP 长连接、QQ 等应用也会在底层 TCP 的基础上实现自己的连接状态检测机制,以确保连接的正常运行。这样的检测可以是定期发送特定的探测数据,如果没有得到预期的回应,就会判断连接状态异常并采取相应的处理措施。
总之,TCP 协议在面对各种异常情况时,采取了多种机制来尽量保证连接的可靠性和正常关闭。应用层也可以根据自身需求实现额外的检测和处理机制来保障连接的稳定性。
4、TCP/UDP对比
- 基于连接与无连接;
- 对系统资源的要求(TCP较多,UDP少);
- UDP程序结构较简单;
- 流模式与数据报模式 ;
- TCP保证数据正确性,UDP可能丢包,TCP保证数据顺序,UDP不保证。