- UDP是无连接通信协议,即在数据传输时,数据的发送端和接收端不建立逻辑连接。
- 也就是当一台计算机向另外一台计算机发送数据时,发送端不会确认接收端是否存在,就会发出数据,同样接收端在收到数据时,也不会向发送端反馈是否收到数据
- 由于使用UDP协议消耗资源小,通信效率高,所以通常都会用于音频、视频和普通数据的传输例如视频会议都使用UDP协议,因为这种情况即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响
- UDP协议的Header包括四个字段: 1. 源端口 2. 目的端口 3. 长度 4. 校验码
- 源端口: 可选字段,表示发送方进程的端口,接收方可根据此字段(不一定准确)发送信息
- 目的端口: 目的端口是数据接收方的端口号,它只在目标的IP地址下才有效
- 长度: 长度是协议头和数据报中数据长度的总和,表示整个数据报的大小
- 校验码: 校验码使用 IP 首部、UDP 首部和数据报中的数据进行计算,接收方可以通过校验码验证数据的准确性,发现传输过程中出现的问题
- TCP是一种面向连接的、可靠的、基于字节流的传输层通信协议. TCP协议建立的是一种点到点的,一对一的可靠连接,与UDP相比以牺牲效率为代价换取高可靠性的服务
- 无差错, 不丢失,不重复, 数据有序
- TCP是双工的协议,会话的双方都可以同时接收、发送数据
- TCP可以接收来自多个应用程序的数据流,用端口号标识他们,然后把他们送给Internet层处理;同时TCP接收来自Internet层的数据包,用端口号区分他们,然后交给不同的应用程序。(UDP同理)
- TCP 报文格式:
序号(seq)
- 长度为四个字节 [0, 4294967295]
- TCP数据是字节流,每个字节都有唯一的序号
- 起始序号在建立TCP连接的时候设置
- 序号表示本报文段数据的第一个字节的序号
确认号 (ack)
- 长度为四个字节 [0, 4294967295]
- 期待收到对方下一个报文的第一个数据字节序号
- 也就是如果确认号= N, 则序号N-1为止的所有数据都已经正确收到
控制位: 总共六个比特位
- URG: Urgent, URG = 1,表示紧急数据
- ACK:Acknowledgment,确认位,ACK = 1时确认号才生效**
- PSH:Push推送位,PSH=1,尽快地把数据交付给应用层
- RST:Reset重置位,RST= 1,重新建立连接
- SYN:Synchronization:同步位, SYN=1 表示这是一个连接请求报文**
- FIN: Finish:终止位,FIN=1 表示释放连接**
窗口
- 长度为两个字节 [0, 65535]
- 窗口指明允许对方发送的数据量
- 因为数据缓冲空间有限, 不能无线缓存数据
- 第一次: SYN = 1, 请求连接,并告诉对方自己的序列号
- 第二次: SYN = 1, ACK=1,确认对方数据并告诉对方自己的数据序列号
- 第三次: ACK = 1, 确认了对方的数据并开始传输数据
为什么不能是两次握手
- 如下图, 如果发起方的第一次连接请求迟迟没有得到回应,则会发出第二个请求
- 如果是两次握手, 则会建立两个连接,造成资源浪费和错误
- 三次握手可以保证发起方忽略第二个应答
- 第一次:FIN=1,seq=u 主动请求中断连接
- 第二次:ACK=1, ack=u+1, 表示确认收到中断报文,并发出最后需要发送的数据
- 第三次:FIN=1,ACK=1,seq=w, ack = u+1,请求中断连接
- 第四次:ACK=1,seq=u+1,ack=w+1 确认中断连接
TIME-WAIT状态
- TIME-WAIT状态发生在第四次挥手之后,主动发尚未完全关闭TCP连接,端口不可复用
- TIME-WAIT状态一般持续2MSL(四分钟), MSL为Max Segment Lifetime,最长报文段寿命,一般为两分钟
- 因为最后一个报文是不会收到确认的,所以为了确定报文一定到达对方,需要一个等待时间。在2MSL的时间内,如果对方没有收到,则会重新进行第三次挥手。
- 同时确保之前的所有报文已经过期
- 因为需要保证可靠性,所以TCP协议需要接收方对每个收到的包进行ACK确认,而接收方只有收到上一个包对应的ACK包,才能继续发送下一个包
- 但是这样效率就会非常低,传输N个包就需要等待N次应答时间,总的传输时间=N份传输时间+N份应答传输时间
- 而滑动窗口协议可以解决这个问题,达到批量传输
发送窗口
- 滑动窗口 分为 发送窗口 和 接收窗口. 客户端和服务器端 都有一个 发送窗口 和 接收窗口
- 发送窗口实际存在于操作系统中,是一块缓冲区,用来存放当前需要发送的数据。本质是一个循环数组的实现。利用三个指针来维护相关的区域。
- “发送窗口”的大小取决于对端通告的“接收窗口”
- 应用层发送数据,就是往缓冲区中写入数据。收到ACK后,就相当于从缓冲区中移除数据,不过并不会真正移除数据,只需要后移对应的指针就可以了
- 应用层会将数据写入到缓冲区中,当超过缓冲区的最大地址后,就循环利用头部,覆盖头部的数据
- 如果这个时候接收一个ack包为37,这个时候发送窗口会向右边移动5位,52-56会变成可用窗口
- 如果发送方发出了ack37的包,意思是下一个需要接收的包是37,也就是37之前的数据全部接收到,即使没有收到ack32-36
滑动窗口如何处理丢包
- ACK丢包:
- 如下图,1001这个ACK丢了,但是2001ACK却已经发送给主机A,说明1-1000这个数据也顺利到达,1001ACK丢了无所谓,只要当前序号开始,就说明之前的数据已经正确传输到达主机B
数据包丢包
- 如下图1001-2000数据包丢了,而2001-3000,3001-4000都顺利到达
- 此时主机B反馈的ACK确认序号始终是1001,主机A如果发现主机B连续发送ACK都是1001,主机A就明白1001-2000这个数据丢包,就会重新传送
- 当主机B重新收到丢失的1001-2000数据后,直接返回ACK4001,因为2001-4000已经接受过(都在缓冲区等待),接下来ACK直接从4001开始。
TCP窗口的拥塞处理
- TCP首部中有一个窗口字段(接收窗口的大小),接受方和发送方通过这个字段,告诉对方一次能够发送多少数据
- 当服务器忙于处理从多个客户端接收的报文, 服务器很有可能因为清理缓存而变得缓慢,无法腾出空间接收新的数据,如果没有流控,则可能会造成丢包和数据损坏。
- 所以当接收窗口所设定的速率无法使服务器 正常处理数据时,接收方会调整接收窗口大小。通过减小返回给发送端的ACK报文的TCP头窗口大小值来实现
- 下图中,服务器初始窗口大小为5000字节。客户端发送2000字节,之后又发送了2000字节,缓冲区中只有1000字节可用。服务器意识到缓冲区正在快速填满,它知道如果数据继续以此速率传输,很快会有报文丢失。为了防止报文丢失,服务器发送确认信息给客户端,更新窗口大小为1000字节。结果,客户端减少数据发送,服务器以可以接受的速率处理缓存内容,即保持数据流以稳定的速率传输。
- 调整窗口大小在两个方向都是可行的。当服务器能够更加快速的处理报文时,它会发送一个较大窗口的ACK报文
- 某些情况下,服务器无法再处理从客户端发送的数据。可能是由于内存不足,处理能力不够,或其他原因。这可能会造成数据被丢弃以及传输暂停,但接收窗口能够帮助减小负面影响。
- 当上述情况发生时,服务器会发送窗口为0的报文。当客户端接收到此报文时,它会暂停所有数据传输,但会保持与服务器的连接以传输探测(keep-alive)报文。探测报文在客户端以稳定间隙发送,以查看服务器接收窗口状态。一旦服务器能够再次处理数据,将会返回非零值窗口大小,传输会恢复。下图示例了零窗口通知过程。
主要包括
- 慢启动算法
- 拥塞避免算法
- 快重传算法
- 快恢复算法
- 详解: TCP的拥塞避免算法
- TCP的报文为 segment. TCP是把数据看成一连串字节流,当应用层传下来的报文(message)太长了,TCP是会把报文切片的,所以TCP的segment的意思是说:我的segment可能是报文(message)的某一段.
- 通过TCP连接给另一端发送数据,你只调用了一次write, 发送了100个字节,但是对方可以分10次收完,每次10个字节;你也可以调用10次write,每次10个字节,但是对方可以一次就收完.
- UDP的报文是datagram. UDP对应用层交下来的报文,不合并,不拆分,只是在其上面加上首部后就交给了下面的网络层. 而对接收方,接到后直接去除首部,交给上面的应用层就完成任务.
- UDP的发送端调用了几次write,接收端必须用相同次数的read读完。UDP是基于报文的,在接收的时候,每次最多只能读取一个报文,报文和 报文是不会合并的,如果缓冲区小于报文长度,则多出的部分会被丢弃.
- 这是一种利用TCP协议缺陷,发送大量伪造的TCP连接请求,使被攻击方资源耗尽(CPU满负荷或内存不足)的攻击方式
- 利用TCP三次握手的缺陷, 对服务器发送伪造大量的假TCP连接请求, 此时服务器会回复ACK确认报文, 然后等待攻击方第三次握手, 而攻击方忽略ACK确认报文, 一直不回复. 服务器会一直重发直至超时. 这些伪造的SYN包将长时间占用未连接队列,其他客户的正常的SYN请求不能被接收,目标系统运行缓慢,造成网络拥堵