TCP协议和UDP协议
(注:本文部分摘自《计算机网络 谢希仁》)
目录
1.1.2每一条TCP连接只能有两个端点,每一条TCP链接只能是点对点的(一对一)
1.传输控制协议TCP
1.1TCP的主要特点:
1.1.1面向连接的运输层协议
(1)TCP的连接
TCP的许多特性都与TCP是面向连接的这个基本特性有关,因此要对TCP的连接有更清楚的了解。
每一条TCP连接唯一地被通信两端的两个端点所确定,所谓的端点就是套接字(或插口)。
套接字的表示方法:在点分十进制的IP地址后面写上端口号,例如IP地址是192.3.4.5,端口号是80,那么套接字就是(192.3.4.5:80) 。
(2)TCP的连接建立
三次握手:TCP建立连接的过程叫做握手,握手需要在客户端和服务器之间交换三个TCP报文段。此过程如下:
(3)tcp的连接释放
四次挥手过程如下:
(4)tcp的有限状态机
可以看我之前的这篇文章,这里不再赘述。
TCP连接的状态——TIME_WAIT的存在意义https://blog.csdn.net/m0_54355780/article/details/121190546
1.1.2每一条TCP连接只能有两个端点,每一条TCP链接只能是点对点的(一对一)
1.1.3TCP提供可靠交付的服务
(1)可靠传输的工作原理
①停止等待协议:
“停止等待”就是每发送完一个分组就停止发送,等待对方确认。在收到确认后再发送下一个分组。
- 无差错的情况下:一端发送,另一端等待并接收
- 出现差错的情况:一端在一段时间(会设置有超时计时器)一直没有收到确认,认为自己刚发送的内容丢失,于是重新发送,这就叫超时重传。这里需要注意三点:第一,发送完自己的分组需暂时保留自己的副本,以防超时重传;第二,分组和确认分组要编号,从而确认哪些分组收到确认,哪些分组没有收到确认;第三,超时计时器设置的重传时间应当比数据在分组传输的平均往返时间长一些。
- 确认丢失和确认迟到:
- 信道利用率
等值等待协议的信道利用情况如下图:
为了提高效率,发送方可以不使用低效率的停止等待协议,使用流水线传输,流水线传输就是发送方可以连续发送多个分组,不必每发完一个分组就停下来等待对方的确认。
②连续的ARQ协议
连续ARQ协议规定:发送方每收到一个确认,就把发送窗口向前滑动一个分组的位置。接收方采用累计确认的方式,也就是说:接收方不必对收到分组逐个发送确认,而是在收到几个分组之后,对按序到达的最后一个分组发送确认。
(2)可靠传输的实现
①超时重传时间的选择
报文段的往返时间RTT:采用自适应算法,记录一个报文段发出的时间,以及收到相应确认的时间。这两个时间之差就是RTT。
平滑的往返事件RTTs:RTT的一个加权平均往返时间
上式的α值在RFC 6298推荐为0.125 。
超时重传时间RTO:报文每重传一次,就把超时重传时间RTO增大一些,取新的重传时间为旧的重传时间的2倍。当不再发生报文段的重传时,才根据下面的式子计算超时重传时间。
②选择确认SACK
如果收到的报文没有差错,但是未按序号,中间还缺少一些数据,使用选择确认可以只传送缺少的数据而不重传已经确认到达接收方的数据。
要使用选择确认,需在TCP首部的选项中加上“允许SACK”的选项,并且双方必须事先商定好。
但是首部最长40字节,如果要报告5个字节块的边界信息,那么5个边界需要2*5*4=40个字节来表述,再加上一个字节指明SACK选项命令一个字节指明SACK占用多少字节,这就一共需要42字节,超出首部长度。因此大多数的实现还是需要重传全部的数据块。
③流量控制
流量控制的目的:让发送方的发送速率不要太快,从而让接收方来的及接收
- 滑动窗口:在 TCP 的报头中有一个字段叫做接收通告窗口,这个字段由接收端填充,是接收端告诉发送端自己还有多少缓冲区可以接收数据。于是发送端就可以根据这个接收端的处理能力来发送数据,而不会导致接收端处理不过来。所以发送端就会有一个发送窗口,这个发送窗 口的大小是由接收端填充的接收通告窗口的大小决定的,并且窗口的位置会随着发送端数据 的发送和接收到接收端对数据的确认而不断的向右滑动,将之称为滑动窗口。(TCP的滑动窗口以字节为单位)p3-p1=A的发送窗口;p2-p1=已发送但尚未收到确认的字节数;p3-p2=允许发送但尚未发送的字节数。此外,需要注意的是,并不是发送方将数据直接发给接收方,而是发送方的应用进程把字节流写入TCP的发送缓存,发送缓存用来暂时存放发送应用程序传送给发送方TCP准备发送的数据以及TCP已发送出但尚未收到确认的数据。接收方的应用进程从TCP的接收缓存中读取字节流,接收缓存用来暂时存放按序到达但尚未被接收应用程序读取的数据以及为按序到达的数据。最后在滑动窗口的部分知识中需要注意三点:第一,同一时刻,发送方的发送端口并不总是和接收方的接收窗口一样大,其会根据网络拥塞情况适当减少自己的窗口值;第二,不按序到达的数据,先临时存放在接收缓存中,等到缺少的字节收到后,再按序交付给上层的应用进程;第三,TCP接收方要有累计确认的功能。
- TCP的传输效率:TCP报文段的发送时机有三个控制机制:第一种,缓存中存放数据达到MSS(最大报文段长度)字节时,就组装成一个TCP报文段发送;第二种,发送方应用进程指明要求发送报文段;第三种,发送方的一个计时期限到了,就把当前已有 缓存数据并且<=MSS装入报文段发送出去。
④拥塞控制
- 满开始:由小到大逐渐增大拥塞窗口数值。
- 拥塞避免:为了防止拥塞窗口增长过大引起网络拥塞,设置慢开始门限。然后拥塞避免的算法思路就是让拥塞窗口缓慢增大,即每经过一个往返时间RTT就把发送方的拥塞窗口加一。
- 快速重传:接收方不要等待中积极发送数据的时候再进行对之前数据的捎带确认,而是收到数据立即发送确认。快重传算法规定:发送方一连收到三个重复的确认,就应当进行快重传。
- 快速恢复:当出现超时的时候,不启动慢开始,而是执行快恢复算法。发送方调整门限值=出现超时的cwnd(拥塞窗口)/2。
1.1.4TCP提供全双工通信
1.1.5面向字节流
流式服务的特点:TCP 字节流的特点,发送端执行的写操作次数和接收端执行的读操作次数之间没有任何数量关系,应用程序对数据的发送和接收是没有边界限制的。
1.2与TCP有关的面试问题
(1)为什么时三次握手,可不可以是两次握手,为什么?
如果是两次握手,那么如果出现这种情况:发送端发送请求连接报文,但是由于在网络中出现了滞留并没有按时到达接收端,等到一段时间发送端再次发送连接请求报文,接收端接收之后并发送确认连接。这样两次握手建立连接1。但是之前在网络中滞留的连接请求报文并没有丢失,于是发送给接收端,接收端误以为建立连接,于是就回复确认建立连接,所以此时又建立了连接2,但是发送端并不会给连接2发送数据,所以接收端一直处于等待,就会浪费接受端许多资源。
三次握手也可以是四次握手:接收端在回复确认建立连接报文的时候,将其分成两个报文段,一个是回复对发送端的连接确认,一个是发送自己的同步报文段。
(2)三次握手时可能出现什么攻击?
可以参考下面这篇文章:
TCP三次握手有哪些漏洞?https://www.cnblogs.com/HuiH/p/12599048.html可能出现的攻击有三种:SYN flood的攻击,TCP全连接攻击,Land攻击。
(3)四次挥手的过程可以用三次完成吗?
关闭连接时,服务器端收到FIN报文,并不会立刻关闭SOCKET,先回复ACK报文,等到服务器端的所有报文都发送完了,才发送FIN报文。所以不能三次完成,将ACK和FIN不能放在一起发送。
(4)对于三次握手四次挥手的面试题,可以看看这个文章
面试官,不要再问我三次握手和四次挥手https://zhuanlan.zhihu.com/p/86426969
(5)同一个端口可不可以被一个 TCP 和一个 UDP 的应用程序同时使用?
可以。原因是端口的唯一性标识是:端口号+协议名称。所以TCP和UDP的端口完全没有任何关系,协议内部端口号唯一。
追问:程序在连接到端口时,怎么知道此时从该端口进来的数据是tcp的还是udp的呢?
操作系统根据接收的IP数据包的首部内的8位协议来判断这是什么报文,从而直接交给相关的内核进程或者协议栈处理。
追问:一个端口是否可以绑定多个端口号?
可以。一个进程可以打开多个文件描述符,每个文件描述符对应一个端口号,所以一个进程可以绑定多个端口号。Linux会给每个socket分配一个唯一的文件描述符,通过这个文件描述符来区分对应的套接字。
追问:一个端口号是否可以被多个进程绑定?
不可以。但是在父子进程中可以实现多进程绑定一个端口号,因为子进程具有父进程的文件描述符副本,可以处理绑定到同样的端口上的连接
追问:一个端口可以同时连接多个TCP和多个UDP吗?
一个端口可以建立多个TCP连接,所谓的同一个端口是指服务器端的ip和port不变,但是只要客户端的ip和port不同就可以。一个端口同一时间只能绑定一个socket。UDP是面向无连接的,所以不存在多个UDP连接,只是服务端接收UDP数据需要绑定一个端口,一个socket只能绑定一个端口而已。
(如果还不是很清楚这方面的问题,可以参考下面几篇文章)
TCP和UDP使用同一端口通信https://blog.csdn.net/szm1234/article/details/116994450一个端口号可以同时被两个进程绑定吗?https://zhuanlan.zhihu.com/p/280672302#:~:text= 由上述结果可知:TCP、UDP可以同时绑定一个端口8888,但是一个端口在同一时刻不可以被TCP或者UDP绑定2次。,原因如下: TCP和UDP传输协议监听同一个端口后,接收数据互不影响,不冲突。快狗二面 一个端口可以 同时TCP 又UDP 吗?https://cloud.tencent.com/developer/article/1813256
(6)同一个应用程序可以创建多个套接字吗?
端口是唯一的,系统中任一个端口只能被一个程序占用。一个程序可以创建多个Socket,但多个Socket是不能共用端口的。
(7)什么是 TCP 粘包,如何解决?
定义:指的是多个报文数据内容融合在一起被接受
解决方案:
①循环接收、发送;即就是一次send,一次recv……
②设置分割标志。
③在头部加上长度控制,然后读取的时候只读取头部信息中指定的长度。
(8)为什么UDP数据包不发生粘包,而TCP会出现粘包?
TCP协议是面向链接的,收发两端都必须要有成对的socket,因此发送端为了将多个发往接收端的包更有效的发送,使用了优化的方法nagle算法。
面向流的服务是没有消息保护边界的。
UDP协议是无连接,面向消息的,支持一对多的模式,所以接收端的套接字缓冲区采用链式结构记录每一个到达的UDP包。
面向消息的通信是由消息保护边界的。
(9)如果接收端填充的接收通告窗口为 0,发送端接下来怎么处理?
接收端通告的窗口大小变成0,发送端会发一个1字节的段,这一个字节段可以是下一字节的数据,如果没有新的数据段发送的时候,就发一个ack,强制接收端重新宣告下一个期望的字节和窗口大小。如果接收方回复窗口大小仍然为零,则发送方的探测定时器加倍。没有收到ACK时,发送探测包的最大次数之后连接超时。
(10)什么叫糊涂窗口综合征?
糊涂窗口综合症是指当发送端应用进程产生数据很慢、或接收端应用进程处理接收缓冲区数据很慢,或二者兼而有之;就会使应用进程间传送的报文段很小,特别是有效载荷很小; 极端情况下,有效载荷可能只有1个字节;传输开销有40字节(20字节的IP头+20字节的TCP头) 这种现象。
要解决这个问题,发送方要把数据累计成足够大的报文段,等到其到达接收方缓存区的一半大小,再发送报文。接收方等待一段时间,使得自己的接收缓存区中能够容纳一个最长的报文段或缓存区有一半空闲,然后再去发送确认报文。
(11)在 TCP 的实现中广泛使用的 Nagle 算法是什么?
若发送应用进程,把要发送的数据逐个字节的送到TCP的发送缓存,则发送方就把第一个数据字节先发送出去,把后面的数据字节都缓存起来。当发送方收到对第一个数据字符的确认后,再把发送缓存中的所有数据组装成一个发送报文段发送出去。
(12)TIME_WAIT 状态存在的原因?
①保证发送端发送的最后一个ACK报文段能够到达接收端,从而避免接收端因为收不到ACK报文段而不按照正常步骤进入CLOSED状态。
②使本链接持续的时间内所产生的所有报文都从网络中消失,避免下一个新连接中出现旧的连接请求报文段。
2.用户数据报协议UDP
2.1UDP协议的主要特点:
(1)UDP是无连接的,可以减少开销和发送数据之前的时延。
(2)UDP使用尽最大努力交付,不保证可靠交付,主机不需要维持复杂的连接状态表。
(3)UDP是面向报文的,一次交付一个完整的报文。
(4)UDP没有拥塞控制,因此网络出现的拥塞不会使得源主机的发送速率降低。
(5)UDP支持一对一、一对多、多对一、多对多的交互通信。
(6)UDP的首部开销小,只有八字节。