目录
上一篇我们对于保证TCP可靠性传输的六个机制有了一定的了解,确认应答和超时重传是保证可靠性传输的最核心机制。这里还有保证可靠性传输的其他四个机制,我们也来对这四个机制进行学习和了解。
1 延迟应答
延迟应答是提高传输效率的机制,基于流量控制来引入的提高效率的机制。
拖延时间,ACK晚一点,应用程序就能从缓冲区多取走一些数据,这样剩余缓冲区空间就能更大一些,得到一个更大的窗口。
实际上TCP的延迟时间不一定用时间来衡量,有可能是是用传输轮次来衡量。
延迟应答的作用就是想方设法让窗口更大一些。
2 捎带应答
捎带应答是基于延迟应答的基础上引入的。
我们典型的网络通信模型是一收一发。TCP中,只要把数据传输过去,对方收到后就会立即由内核返回一个ACK确认报文,响应数据则是由应用程序里负责传输的。由于四次挥手中不能合并,但是延时应答需要稍等一会儿返回ACK,这是正好业务上也要返回这个响应(应用程序调用socket的write方法OutputStream,把数据交给内核,内核进行封装进行发送),因此就把两个报文合并在一起,这就是前面在了解四次挥手时存在的可以合并的情况。
这两个操作是否能合并是偶然的,不是必然的,不一定每次都能碰巧一起发送。
3 面向字节流(粘包问题)
前面我们也了解过面向自己节流,在面向字节流中有一个典型的问题叫做粘包问题。
TCP或者其他面向字节流的传输方式都有一个接收缓冲区,发送方得到接收方的回复,这是发送方的应用程序就需要从接收缓冲区读取数据,但是由于是面向字节流的,无法确定完整的应用层数据报如何分割,此时就会可能会发生粘包问题,就是TCP自身对于应用层数据报是无法进行区分的,而UDP就不会存在这样的问题,UDP是面向数据报的,每一个UDP数据报就对应一个应用层报文。
如何解决粘包问题?其实就只需要在定义应用层数据协议的时候,明确包和包的边界就可以了。
方法一:通过分隔符,比如使用;作为包的结束表示;
方法二:在数据包的开头位置声明包的长度。
4 TCP中的异常处理
4.1 程序崩溃
程序崩溃属于进程异常退出,操作系统就会回收进程的资源,包括释放文件描述符表,相当于调用socket的close,执行close就会触发FIN报文(结束报文段),进一步开始四次挥手。这种情况和普通的四次挥手没有区别。
4.2 正常关机
这个和上述程序崩溃的情况相同,最终也是进行四次挥手。
4.3 强制关机(主机掉电)
这种异常会发生以下两种情况:
①如果掉电的是接收方,发送方不知道对方出现异常,继续发送数据,此时发送的数据没有收到ACK,发送方就会触发超时重传,重传几次后仍然没有应答,此时就会尝试重置连接(复位报文段RST),重置连接失败后就会放弃连接。
②如果掉电的是发送方,接收方就持续等待,等待一段时间后就会发送一个心跳包,心跳包是周期性触发的,是一个简单的不携带任何业务的数据的包,就是测试一下对方还在不在,如果对方不返回心跳包,说明对方挂了,此时就会放弃连接。
4.4 网线断开
网线断开的情况和主机掉电的情况一样,就是两端各自按照上述的两种情况分别进行测试。
5 TCP和UDP对比
5.1 各自的特点
这个在前面 网络编程基础(socket)这篇中有介绍。网络编程基础(socket)_咸鱼没有不粘锅的博客-CSDN博客
5.2 应用场景
在有可靠性要求的场景就会用到TCP。
不要求可靠性,要求传输效率,此时就需要用UDP。
既要保证可靠性传输又要保证效率的协议还有KCP。
5.3 如何使用UDP实现可靠性传输
这个就是把TCP的机制搬到UDP上使用,基于UDP在应用层来实现确认应答、超时重传、引入序列号等机制。