目录
前言
一.TCP
1.1 什么是TCP?
1.2TCP的连接与释放(确认应答机制)
1.2.1三次握手
1.2.2四次挥手
1.3TCP滑动窗口(效率机制)
1.4流量控制(安全机制)
1.5拥塞控制(安全机制)
1.6延迟应答(效率机制)
1.7捎带应答(效率机制)
1.8心跳机制(安全机制)
1.9粘包问题
二.UDP
2.1什么是UDP
2.2UDP的传输数据
2.3UDP的单播、广播、组播
三.TCP和UDP的区别
🎁个人主页:tq02的博客_CSDN博客-C语言,Java,Java数据结构领域博主
🎥 本文由 tq02 原创,首发于 CSDN🙉
🎄 本章讲解内容:TCP和UDP的详细讲解🎥学习专栏: C语言 JavaSE MySQL基础 多线程学习
前言
本文讲解TCP的三次握手和四次挥手,TCP的安全机制和效率机制,TCP协议段格式的详细数据解析、UDP的讲解、TCP和UDP的区别。
预备知识:
网络的吞吐量:网络在单位时间内能够传输的数据量。它是衡量网络性能的一个重要指标,通常用单位时间内传输的数据位数或字节数来表示。
计算方法:吞吐量 = 数据传输的总字节数 / 传输时间
数据传输的总字节数可以通过网络传输过程中捕获的数据包大小之和来计算,传输时间是指从发送方发送数据开始到接收方完全接收数据所经过的时间。
一.TCP
1.1 什么是TCP?
TCP和TCP/IP是不一样的,TCP/IP是一种模型,而TCP是传输层的协议,是TCP/IP体系中非常复杂的一个协议。TCP: Transmission Control Protocol (传输控制协议),传输层协议。
TCP的作用:
- 处理应用层的数据,在计算机网络中传输数据。
- 确保数据在发送和接收时不会丢失、损坏或重复。
TCP的特点:
有连接 可靠传输 面向字节流 有接收缓冲区,也有发送缓冲区 大小不限确认应答 和 超时重传是 TCP 可靠性中最核心的机制
源/目的端口号:表示数据是从哪个进程来,到哪个进程去;
32位序号:指明本报文段所发送的数据的第一个字节的序号。TCP连接中传送的字节流中的每一个字节都按顺序编号。
32位确认号:指明期望收到对方下一个报文段第一个数据字节的序号。若确认号,则表明:到序号为止的所有数据都已正确收到。
- URG:紧急指针是否有效
- ACK:确认号是否有效
- PSH:提示接收端应用程序立刻从TCP缓冲区把数据读走
- RST:对方要求重新建立连接;我们把携带RST标识的称为复位报文段
- SYN:请求建立连接;我们把携带SYN标识的称为同步报文段
- FIN:通知对方,本端要关闭了,我们称携带FIN标识的为结束报文段
1.2TCP的连接与释放(确认应答机制)
TCP对数据传输提供的管控机制,主要体现在安全和效率。在保证安全的前提下,尽可能提高传输效率。因此产生了三次握手。而断开连接时,则是四次挥手
1.2.1三次握手
三次握手是指客户端与服务器建立连接的方式,客户端主动发起建立的应用进程,服务器被动等待建立的应用进程。
其中建立连接的重要字段是:
- 序号(sequence number):seq序号,占32位,用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记。
- 确认号(acknowledgement number):ack序号,占32位,只有ACK标志位为1时,确认序号字段才有效,ack=seq+1。
- 标志位(Flags):共6个,即URG、ACK、PSH、RST、SYN、FIN等
具体过程:
1.TCP服务器先创建传输控制块,用于存储TCP连接的重要信息(例如:当前的发送和接收序号、指向发送和接收缓存的指针等),等待接收客户端的TCP客户端的连接请求---监听状态
2.TCP客户端创建传输控制块,然后向服务器发送TCP连接请求报文段,进入同步已发送状态
- TCP 连接请求报文段首部中的同步位SYN被设置为1,,表明这是一个tcp连接请求报文段。
- 序号字段seq被设置了一个初始值x作为TCP客户进程所选择的初始序号。
3.TCP服务器进程收到TCP连接请求报文段后,如果同意建立连接,则向TCP客户进程发送TCP连接请求确认报文段,并进入同步已接收状态。
- 该报文段首部中的同步位SYN和确认位ACK 都设置为1,表明这是一个TCP连接请求。
- 序号字段seq被设置了一个初始值y,作为TCP服务器进程所选择的初始序号。
- 确认号字段ack的值被设置成了x+1,这是对TCP客户进程所选择的初始序号seq的确认。
结论:TCP规定,SYN报文段不能携带数据,但要消耗一个序号;ACK报文段可以携带数据,但如果不携带数据则不消耗序号。并且seq是供对方选择的序号,而ack则是对传递过来的seq的确认。ack=seq+1.
疑问:如果传递的过程中信息未传递过去,会发生什么呢?
答,服务器或者客户端会等待一定时间,如果未收到信息,会重新发送信息 ----超时重传
疑问:如果只是重新发送信息之后,之前的信息又收到了,会发送什么呢?
答:接收方会根据序号进行去重操作,
疑问:为什么会是三次握手呢?不能是二次或者四次呢?
答:如果是两次握手,客户端发起连接,但若未接收到服务端的回应,服务端就不知道是否客户端接收到回应;而至于四次等多次,属于浪费资源,三次可以,为什么还要四次呢?
三次握手的主要用处:验证通信路径是否正常,双方发送和接收是否正常,协商必要参数,使服务端和客户端使用相同的参数进行信息传输。
1.2.2四次挥手
四次挥手,说明客户端和服务端断开需要四个流程,而且断开连接,也是需要客户端主动断开。此时涉及到的标志位:FIN
具体过程:
- 客户端调用close方法,发送一个FIN报文(FIN标记位设置为1)给服务端,客户端进入FIN-WAIT-1状态。
- 服务端收到FIN报文,向客户端发送ACK应答报文,以客户端FIN报文的序列号seq+1作为ACK应答报文的确认序列号ack=seq+1.服务器进入CLOSE_WAIT(等待关闭)状态。此时此刻TCP处于半关闭状态
- 客户端收到服务器的ACK应答报文段后,进入FIN_WAIT_2状态,服务器打算彻底断开连接,向客户端发送连接释放(FIN)报文段,之后服务器进入LASK_ACK(最后确认)状态,等待客户端的确认。
- 客户端收到来自服务器的连续释放报文,会向服务器发送一个ACK应答报文,让服务器进入关闭状态,而客户端会进入TIME_WAIT(时间等待)状态,等待2MSL后,客户端才进入CLOSE状态。此时此刻,连接正式关闭。
总结:FIN 段是可以携带数据的,但无论是否携带数据,都需要消耗一个序列号。
半关闭状态:客户端发送 FIN 包以后不能再发送数据给服务端,但是还可以接受服务端发送的数据。
疑问:为什么TIME_WAIT等待的时间是2MSL?
答:MSL(Maximum Segment LifeTime)是报文最大生成时间,它是任何报文在网络上存在的最长时间,超过这个时间的报文将被丢弃。因此如果2MSL内服务器未收到应答报文段,则重发FIN报文段,如果客户端收到了FIN报文段,那么2MSL的时间将会被重置。如果在2MSL时间段内,没有收到任何数据报,客户端则会进入CLOSE状态。
疑问:服务器可以主动断开连接吗?
答:可以的,率先请求关闭的一方才会进入TIME_WAIT(时间等待状态)
疑问:为什么中间的ACK和FIN不能合并变成三次挥手?
答:ACK报文则是由系统内核来完成,FIN是应用程序通过close()方法执行,执行close()方法会触发内核发送FIN报文。什么时候调用close()方法,这是由用户态决定的,若是服务器还要大量数据需要处理,处理完毕才可以调用close()方法。
1.3TCP滑动窗口(效率机制)
在上述应答机制当中,我们可以发现,安全性的确高,每一个发送的数据段都有一个ACK确认应答,收到ACK再发送下一个数据段。但是也有一个明显的缺点,性能很差,效率低下,数据往返时间过长!
如上图,数据传递,服务器每确认应答,客户端才能发送下一个数据段,耗时过长。
问:那么有什么方式可以修改呢?让效率提高呢?
答:我们可以采取一次发送多条数据,提高效率,这就是滑动窗口
注解:
- 滑动窗口拥有大小,而窗口大小指:客户端无需等待确认应答而可以继续发送数据的最大值
- 上图窗口大小为4个,发送前四个段,不需要等待服务器的ACK。
- 客户端收到一个ACK时,滑动窗口可以向后移动,可以继续发送第五个段的数据。
- 操作系统内核为了维护这个滑动窗口,需要开辟 发送缓冲区 来记录当前还有哪些数据没有应答;只有确认应答过的数据,才能从缓冲区删掉;
-
通信双方都有发送缓冲区和接收缓冲区;
服务器:
发送缓冲区(发送缓冲区窗口)
接收缓冲区(接收缓冲发窗己)客户端:
发送缓冲区(发送缓冲区窗口)
接收缓冲区(接收缓冲发窗己)
疑问:如果产生丢包呢?客户端发送时,丢包又或者服务器传回来的ACK丢包了呢?
答:分情况考虑,看下文
疑问:那么我的滑动窗口是不是越大越好呢?
答:理论上越大越好,但是滑动窗口越大,越容易导致丢包等反应。
疑问:那么滑动窗口应该为多大呢?
答:我们可以通过流量控制的方法,见下文。
情况一:数据包已经抵达,ACK被丢了。
当ACK丢失了,客户端未收到,会继续等待,而服务器超时重传,重新发送
情况二:客户端发送的数据包丢死了。
服务器(主机B)会一直发送,我需要的是丢失的数据段,客户端(主机A)收到三个相同的确认应答时,会进行重传,再将丢失的数据段发送给服务器。服务器处理之后,再发送的ACK则是7001
1.4流量控制(安全机制)
在滑动窗口中,我们说过滑动窗口不是越大越好,接收端处理数据段能力是有限的,如果发送端发的数据太快,导致接收端的缓冲区被打满,这个时候,发送端进行发送,会导致丢包重传等后果。
对于上述情况,TCP根据接收端的处理能力,决定发送端的发送速度。可称:流量控制。
- 接收端将可接收的缓冲区大小放入 TCP 首部中的 "窗口大小" 字段,通过ACK端通知发送端;
- 接收端一旦发现自己的缓冲区快满了,就会将窗口大小设置成一个更小的值通知给发送端;发送端接受到这个窗口之后,就会减慢自己的发送速度;
- 如果接收端缓冲区满了,就会将窗口置为0;这时发送方不再发送数据,但是需要定期发送一个窗口探测数据段,使接收端把窗口大小告诉发送端。
1.5拥塞控制(安全机制)
拥有了滑动窗口,TCP高效可靠的发送大量的数据,并不会出现什么问题,但是思考一下,在网络中,拥有很多计算机,如果它本身的网络状态就已经拥挤了,在不知情下,贸然发送大量数据,数据包将会丢失或延迟,导致通信质量下降。
因此产生了拥塞控制:拥塞控制的目标是通过调整发送数据的速率,以避免网络拥塞的发生。
TCP实现拥塞控制的方法:
- 慢启动:在建立连接时,发送方将以较小的速率发送数据,并以指数级别增长速率,直到网络出现拥塞。
拥塞避免:慢启动过程结束之后,发送方将增长速率变为线性增长,
快速恢复:当发送方检测到丢失的数据包时,通过重传丢失的数据包而不是等待超时,从而快速恢复拥塞窗口大小
详细讲解一下慢启动策略:
此时此刻,我们需要引入一个新的概念词:拥塞窗口。 个人而看,相当于滑动窗口的大小调节
拥塞窗口解析:
- 发送开始时,定义的拥塞窗口大小为1,每次收到ACK应答时,拥塞窗口加1.
- 而客户端接收的ACK应答数据包时,将拥塞窗口和接收的数据包的窗口大小作为对比,取最小值。
- 虽然看上去每次拥塞窗口接收应答时,只加1,但实际上以指数级别增长,只是前期较慢,后期增长速度贼快。
拥塞窗口的数量详细变化图:
讲解:
- 拥塞窗口先是以指数级别增长,但是慢启动有一个 阈值 ,但拥塞窗口超过这个阈值 就会停止指数增长,而是以线性增长。也就是说,慢启动---->拥塞控制。
- TCP启动时,慢启动的阈值等于窗口的最大值,而每一次超时重发时,阈值会变为原来的一般,同时拥塞窗口变为1
注:慢启动的目的是在不造成网络拥塞的前提下,尽可能地提高TCP连接的传输速率。
少量的丢包,我们仅仅是触发超时重传;大量的丢包,我们就认为网络拥塞。
1.6延迟应答(效率机制)
延迟应答也是TCP协议为了提高效率的一种机制;从滑动窗口中,我们可以知道,客户端给服务器一次性发送多个数据,而服务器每接收一个正确的数据,就会返回一个ACK应答,那么如果服务器稍微等待一会,是不是可以减少ACK的应答次数呢?
延迟应答:接收端在接收到数据后,并不立即发送ACK报文进行确认,而是等待一定时间(通常是200ms)后再发送ACK报文。
作用:将多个ACK报文合并在一起发送,减少网络中的报文数量,提高网络利用率。
形式图:
图解:我们可以看见主机B在接收到数据1-1000时,不作出应答,但是在接收1001-2000时,作出应答, 提示:不是主机A接收一个ACK才可以发送一个数据,因为有滑动窗口存在。
疑问:所有的数据包都可以延迟应答嘛?
答:错误,有两种限制,
- 数量限制:每隔N个包就应答一次;
- 时间限制:超过最大延迟时间就应答一次;
注:窗口越大,网络吞吐量就越大,传输效率就越高。我们的目标是在保证网络不拥塞的情况 下尽量提高传输效率。
1.7捎带应答(效率机制)
在延迟应答的基础上,我们可以发现很多情况下,客户端和服务器在应用层也是一发一收的,那么是否可以在客户端发送信息给服务器时,服务器回复信息时,ACK应答可以借助信息同时给客户端呢?是的,可以的。
捎带应答:指在发送端发送数据时,接收端可以在返回的ACK报文中携带已接收的数据序列号信息,以便发送端在收到ACK报文后知道哪些数据已被成功接收。
图解:在进行数据传输时,同时传输了ACK应答,这样发送端就不需要等待接收端的确认ACK报文了,从而提高数据传输效率。
1.8心跳机制(安全机制)
心跳机制是指在TCP连接建立后,为了保持连接的稳定性和可靠性,定期发送小型的探测报文(心跳包)给对方,以确保对方处于活跃状态。如果在一定时间内没有收到对方的回复,则认为连接已经断开,并进行相应的处理(如重新建立连接)。
1.9粘包问题
什么是粘包问题?包是什么?为什么会产生粘包?如何解决呢?
粘包问题
TCP粘包是指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾。
传输层:TCP是一个一个报文过来的。按照序号排好序放在缓冲区中应用层:看到的只是一串连续的字节数据,不清楚从哪个部分到哪个部分是一个完整的应用层数据包。
包:应用层的数据包。
TCP的协议头,没有报文长度,所以不清楚完整数据包的长度,但是会有一个序号,使包按顺序排放在缓冲区中
粘包问题的产生
- 发送端需要等缓冲区满才发送出去,造成粘包
- 接收方不及时接收缓冲区的包,造成多个包接收
注:UDP有报文长度的字段,有明确的数据边界,因此不会产生粘包问题。
粘包问题的解决方法
明确两个包之间的边界。在应用层确定数据边界,完成字节流解析。
- 发送固定长度的消息(局限性较大,不推荐)
把消息的尺寸与消息一块发送
使用特殊标记来区分消息间隔
将第二种和第三种结合起来确定数据边界,做字节流解析的方法:
- 双方约定通讯格式为:HEAD××数据包,其中HEAD为特殊标记,用来做消息分割(双方要约定数据包不包含消息分隔符HEAD,否则会造成数据解析错误); xx为N个字节的数据长度;数据包为实际的数据内容。
- 发送方按照该格式做数据封包,接受者按照该格式解析数据。
- HEAD作为特殊标记分割了各个消息,之后解析出数据长度后,按照该长度解析后面的数据,通过数据长度也可以知道本次接收到的消息是不是完整的消息。
二.UDP
2.1什么是UDP
UDP (User Datagram Protocol,用户数据报协议):应用程序提供了一种无需建立连接就可以发送封装的 IP数据报的方法。
UDP和TCP都是传输层协议。
UDP的作用:
- 应用于数据量大且精确性要求不高的数据传输,传输效率高
例如:我们平常在网站上观看视频或者听音乐
UDP的特点:
- 无连接----通过对端的ip和端口直接进行传输
- 不可靠----没有安全机制,即使发送失败,也不给应用层返回错误
- 面向数据报---应用层交给UDP报文,UDP原样发送,不拆分不合并
- 只有接收缓冲区,没有发送缓冲区
- 大小受限-----最大长度为64k
UDP的协议段格式:
- 源端口和目的端口:表示数据是从哪个进程来,到哪个进程去;
- 总长度:报文长度
- 校验和:核对信息,若错误,直接丢弃
- 数据区:可有可无
从协议段格式,我们可以清晰的发现,十分简单,与TCP差别巨大。
2.2UDP的传输数据
UDP的传输数据相当于寄信,只管丢入邮箱,不管有没有在中途丢失。
发送时:先把数据放到报文,写到缓冲区字节数组再传送。
接收时:从缓冲器数组读取,打包到报文。
2.3UDP的单播、广播、组播
单播:用于两个主机之间端对端的通信。即一对一(客户端与服务器端点到点连接)。 类似于:微信私聊
广播:用于一个主机对整个局域网上所有主机通信。即一对所有。广播禁止在Internet宽带网上传输(广播风暴)。
类似于:微信的群发功能,告知每一个人
组播(多播):对一组特定的主机进行通信,而不是整个局域网上的所有主机。即一对一组
类似于:微信群聊
注:只有UDP才能有广播、组播的传递方式。而TCP是一对一连接通信。
IP地址的区别
- 广播:主机发送广播消息时,需要指定目的IP地址
255.255.255.255
和接受者的端口号。 - 多播:在多播系统中,有一个源点一组终点。这是一对多的关系。在这种类型的通信中,源地址是一个单播地址,而目的地址则是一个组地址。
三.TCP和UDP的区别
特征点 | TCP | UDP |
传输可靠性 | 可靠 | 不可靠 |
传输方式 | 面向连接 | 非连接 |
传输的数据 | 保证数据顺序 | 拥有数据长度 |
速度 | 慢 | 快 |
系统资源要求 | 多 | 少 |
数据传输模式 | 流模式 | 数据报模式 |
应用场景 | 文件传输 | 通信领域 |
信息传输对象 | 一对一 | 一对一、一对多 |
应用层协议 | HTTP、HTTPS、SSH、Telent、FTP、SMTP | NFC、TFTP、DHCP、BOOTP、DNS |
注:都是全双工(接收端和发送端可以互相通信)
问:TCP为什么复杂?
答:因为既要保证可靠性又要提高性能。
- 可靠性:校验和、序列号、确认应答、超时重发、连接管理、流量控制和拥塞控制
- 提高性能:滑动窗口、快速重传、延迟应答、捎带应答。
提示:本文只是讲解TCP和UDP的协议格式,以及作用,若需要网络编程编写TCP和UDP,可以通过Socket套接字。