UDP和TCP是传输层协议
协议特点
连接:通信双方需要提前保留对方的信息
无连接:通信双方不需要保存对方信息 ,指定ip和端口号就可以传输
可靠传输:数据包不会丢失,丢失后会重传
不可靠传输:传输过程数据包可能丢失,发送数据后不关心对方是否接收到数据,所以丢失也不会重传
面向字节流:文件操作就是字节流,读写字节可以非常灵活,10个字节可以读10次,10次可以读100个字节。TCP跟文件操作有相同特点。
面向数据报:传输数据的基本单位是一个UDP数据报,读写只能操作一个完整的数据报,不能读半个数据报。
全双工:一条链路可以进行双向通信
半双工:一条链路只能进行单向通信
UDP
协议特点:无连接,传输不可靠,面向数据报,全双工。用在对数据传输速率高的场景。
报文格式
UDP数据报=UDP报头+UDP载荷(网络层的数据报)
报头:源端口,目的端口,报文长度,校验和。分别占两个字节。
16位UDP长度,表示报文总长不超过64字节;如果我们要传输的数据超过64K,就需要再应用层手动的分包,多次发送,并在接收端手动拼接.
校验和:验证数据报的安全性,如果校验和出错,就会将数据报丢弃.
TCP
特点:有连接,传输可靠,面向字节流,全双工。
报头:
源端口,目的端口,源IP,目的IP
序号和确认序号: 和后面的确认应答机制有关
窗口大小:和后面的流量控制机制有关
报头的六个标志位:URG,ASK(应答报文),PSH,RST(重置报文),SYN(同步报文),FIN(结束报文)
发送哪个报文,就是将报头中六个标志位的相应bit置为1。URG,PSH是用来处理特殊情况的报文。
TCP协议核心机制
1.确认应答
可靠性传输是TCP协议最核心的特点,确认应答是保证可靠性的核心机制 ,让数据尽可能的传输给对方。
首先要确定数据是否真的传输到了对方。如果对方收到了数据,就会返回一个应答报文ACK,传输方接收到ACK报文,就确认数据对方已经收到。
TCP将每个字节进行了编号,即为序列号,ACK带有确认序列化,即收到的最后一个字节的序号+1,表示下次传输数据的起始序号.
(引入序号和确认序号,确认传输数据和应答报文之间的对应关系。
序号:按字节编号,连续递增,tcp报头只保存第一个字节的编号
确认序号:收到的最后一个字节的序号+1,表示确认序号之前的数据都已经收到,后面要发送从确认序号开始编号的数据。)
2.超时重传
网络通信 的设备存在转发上限,如果接收的数据达到上限,多出的数据就会被丢弃。丢包这件事是客观存在并不可预估的,解决丢包事件就需要超时重传。当接收方没有接收到数据就不会回应ACK报文,当超过一定时间发送方没有收到ACK报文就会重新传输数据包。超时时间动态变化,重传的次数增加,时间就变长,降低重传的概率。
发送方无法确定是传输的数据丢了还是ACK应答报文丢了,就会重传导致接收方可能收到两份数据。接收方有一个数据缓存区(类似带有优先级的阻塞队列的结构),来根据数据序列号去重,排序(避免重复数据和数据后发先至产生影响)。当有数据到达就进入缓存区,有序列号重复的数据就丢掉,排序确保先发送的数据先被读取。程序进行读取后的数据,就被缓存区删掉。
当超时重传高达一定概率,就会触发RST“重置报文”,清空之前的中间状态,重新建立连接发送数据,还没有效果就 断开连接(删除对方信息)。
确认应答和超时重传是保证可靠传输的最重要机制。
3.连接管理
三次握手:建立连接时的准备工作
四次挥手:断开连接时的准备工作
三次握手
握手:发送不带有业务数据的数据报(报文载荷为空),尝试建立连接。
连接:通信双方保留对方的信息(IP,端口号)
一次握手:客户端发送SYN 报文,表示请求和服务器建立连接。(第一次只能是客户端)
二次握手:服务器发送ACK,SYN报文,表示收到,可以建立连接(ACK,SYN两个报文是内核控制的,可以同时自动发送 。分为两次发送的话,传输过程封装分用的会增加开销)
三次握手:客户端发送ACK,表示收到
三次握手的意义
1.确认通信路径是否通畅,报头中 包含IP和端口号等信息,让对方知道IP和端口号,才算是建立连接,后续才能交流和通信。
2.验证通信双方的接收能力和发送能力
3.通信双方协商一些必要的数据,比如序列起始号
三次握手不能变成两次,少了最后一次服务器无法验证客户端的接收能力和自身的发送能力,是ACK+SYN没发送出去,还是发送出去没收到,这就无法验证,反正不能不能建立连接。也不能变成四次,因为没必要。
传输层的协议,由操作系统内核完成,当我们new Socket对象时,操作系统内核就实现三次挥手建立连接了,对象调用accept()就是应用层将内核获取的连接信息取出来。
重要状态
listen:服务器的状态,绑定端口号后就进入listen状态,准备就绪等待客户端连接。
established:建立连接完成,随时准备数据通信。
四次挥手
挥手:发送不带业务数据的数据报,进行断开连接。服务器和客户端都可以先挥手。当进程结束就会触发四次挥手,释放文件描述符的资源。
断开连接:删除对方的信息,就无法进行后续通信。
如果是客户端先挥手:
第1次挥手:客户端发送FIN报文(客户端的进程结束或者调用socket.close()时发送)
第2次挥手:服务器发送ASK(收到FIN报文,立即回应ASK报文表示收到。这是由操作系统内核完成的)
第3次挥手:服务器发送FIN(接收到客户端的FIN报文后,服务器的scanner.haseNext()就感知到连接断开,没有数据了。但是当socket.close()或者进程结束时,服务器才会发送FIN报文,这是应用层控制的。停止处理请求到结束进程之间可能会有其他代码逻辑,跟系统内核自动发送ASK很可能不是同一时刻,不是同一时刻就不能跟ASK报文一起发送。)
第4次挥手:客户端发送ASK(收到服务器的FIN报文进行的回应)
重要状态
CLOSE_WAITE :收到FIN报文后进入等待程序调用close状态,如果程序出现大量等待关闭状态,可能是应用程序调用close()不及时,或者没调用。
TIME_WAITE:相当于超时重传,当第三次挥手接收方接收到FIN报文后进入TIME_WAITE状态,然后给对方发送ACK应答报文,如果等待一定时间收到重传FIN报文的话,那对方就没收到ACK,接收方就得再次发送ACK报文,等待一定时间没收到重传的FIN的话,那就可以认定对方收到了,就可以断开TCP连接。真正断开连接释放资源,是等四次挥手后。程序调用close()发送FIN报文是通知断开连接,不是立即断开。
如果出现大量TIME_WAITE说明服务器触发了太多主动断开TCP连接的操作,一般是让客户端主动断开比较合理。
4.滑动窗口


窗口大小:
不用等待ASK报文应答而可以继续发数据的最大值,上图窗口大小为4000个字节.窗口越大,网络吞吐量越大.

5.流量控制
接收端处理数据的能力是有限的,当缓冲区的数据满了,就会导致丢包 ,仅仅是通信过程中数据转发会丢包,服务器的阻塞队列接收数据处理不过来也会丢包。超时重传等机制.
TCP协议中,发送端根据接收端处理数据的能力,调整发送数据的速度,称为流量控制,在TCP报头中,有16位记录窗口大小的位置.接收端可以动态调整窗口大小的值,发送端根据ACK报文的报头信息进行相应的流量控制.窗口越大,网络吞吐量越大. 当缓冲区满了,发送端就不会发送数据,而是发送窗口探测报文,探测缓冲区的大小.
目的:解决接收方处理能力不足的问题,防止发送方发送数据过快导致接收方缓冲区溢出。
6.拥塞控制
和流量控制一样,是和滑动窗口搭配使用的机制。一开始不知道网络的拥堵情况,TCP启动慢启动机制, 先少量发送数据,探探路,此处引入⼀个概念程为拥塞窗⼝,发送开始的时候, 定义拥塞窗口大小为1;每次收到⼀个ACK应答, 拥塞窗口加1;
目的:解决网络资源过载(如路由器队列满、链路拥塞)的问题,避免因网络拥塞引发丢包或全局吞吐下降。
阻塞窗口动态变化。1.开始少量发送数据,试探通信是否通畅2.指数式增长数据量,3.到达一定阈值,线性增长 4.出现丢包就 缩小窗口到原来的一半,再线性增长.
7.延时应答
窗口大小决定传输速率,当服务器接收到数据,不立即 发送ACK报文,而是等服务器处理部分数据再发送,使缓存区剩余空间更大,再发送报文.那后续通信一次发送端能发送更多的数据。减少频繁的接收和应答的开销。在保证网络不拥塞的情况下尽量提高传输效率.
不是所有包都要延迟应答:
时间限制:超过最大延迟时间就应答一次
数量限制:每接收N个包后应答一次;
8.捎带应答
配合延时应答的机制。当服务器接收到请求,返回ACK报文时会延时应答,在ACK等的这一会,程序如果正好要返回相应数据,就会捎上ACK报文一起发送,在 TCP报头ack这里把确认编号/窗口大小给设置好再发送。
9.面向字节流
创建⼀个TCP的socket, 同时会在内核中创建⼀个 发送缓冲区 和⼀个 接收缓冲区;
调⽤write时, 数据会先写⼊发送缓冲区中;如果发送的字节数太长, 会被拆分成多个TCP的数据包发出;
字节流的特点就是一次读取的字节个数是没有要求的,能读多少读多少,所以服务器不知道数据包之间的界限,可能出现粘包问题,需要采取一定措施:
1. 定义分隔符
2.约定包的长度
10.异常情况
1.进程崩溃
崩溃结束跟正常结束进程一样,操作系统都会进行四次挥手,断开连接,释放PCB,释放文件描述符表。(进程没了但是会触发操作系统发送FIN报文,ACK报文断开连接)
2主机被主动关机
正常关机操作系统会尝试结束所有进程再进入关机流程。
A进程发送FIN报文后,B进程收到后回复ASK,准备关闭进程发送FIN报文,如果A没回应ACK,就触发重传机制,A还是没有响应就不管了,断掉连接,关闭进程。所以就算四次挥手没有挥完,也可以断掉TCP连接。
3.主机掉电(被动没电)
如果B是接收方掉电了:
发送方A发送数据不会收到B的ACK,就触发重传机制,直到发送重置报文,还是没有响应就会单方面删掉对方信息,断掉连接。
如果A是发送方掉电了:
接收方B不知道什么时候A会发数据,是暂停一会发送还是A进程瘫痪了。在一定时间没有收到数据就会给A发送“心跳包”,没有载荷的数据包,为了触发A发送ACK报文,如果B发送多次心跳包A都没有回应,那就认为A挂了,就会断掉连接。
4.网线断开
A和B建立TCP连接
A是发送方:触发重传机制,发送RST重置报文
B是接收方:发送心跳包,没有响应断开连接
跟第三种情况一样,A,B分别断开连接
如何使UDP实现可靠性传输
在UDP中引入确认应答,超时重传,连接管理机制,等建立连接后每发送一个UDP数据包都有对应的ACK应答报文,确认序列号等表示收到的,发送方才接着发送数据。这样来保证数据传输的可靠性。引入滑动窗口,流量控制,拥塞控制,延时应答,捎带应答机制来保证数据传输可靠性的前提下,提高传输的效率。