• 【javaEE】网络原理(传输层Part3)


    努力经营当下,直至未来明朗!


    前言

    一个人最大的痛苦来源于对自己无能的愤怒

    Hi,这里还是不想秃头的宝贝儿!要努力不秃头啊!
    学习
    本文主要介绍的是TCP提高效率的机制:延迟应答、捎带应答,以及TCP面向字节流的特性以及TCP的异常处理。

    【回顾TCP】
    ① 确认应答:保证可靠传输的最核心机制
    ② 超时重传
    ③ 连接管理:三次握手(投石问路、发送能力和接收能力、协商参数)、四次挥手
    ④ 滑动窗口
    流量控制(通过接收方的处理能力/内核剩余接收缓冲区 来对发送方作出限制)
    ⑥ 拥塞控制(中间节点)


    TCP相关机制

    7. 延迟应答

    【延迟应答】:提高传输效率的机制

    1. 延迟应答 是基于流量控制来引入的提高效率的机制
    2. 延迟应答:返回ACK的时间稍微晚一点,不是立即返回,此时应用程序就会有时间来消费内核接收缓冲区中的数据,使得接下来ACK返回的窗口略大于立即返回的窗口。
    3. 实际TCP的延时时间不一定非用时间来衡量,也可能是传输轮次来衡量。

    8. 捎带应答

    1. 捎带应答是基于延迟应答的基础上引入的
    2. 网络通信中,典型的通信模型是一发一收。
    3. TCP中,只要把数据传输过去,对方收到后就会立即由内核返回一个ACK确认报文;而响应数据则是由应用程序负责传输的。所以,返回ACK和响应这两个操作是不同的时机传输的,就不能够把两次传输合并起来;但是延迟应答就会让ACK延迟返回,会稍微等一会儿,而在等待之后业务如果刚好也要返回响应,此时就可以把ACK与响应两个报文合二为一了(是由内核处理的,应用程序处理的响应也要经过内核,即:应用程序是调用socket的write方法把数据交给内核,内核进行封装,然后发送)。
    4. 补充:SYN-同步报文段; FIN-结束报文段; ACK-确认报文段

    TCP补充

    【面向字节流】

    1. 面向字节流中存在一个典型问题:“粘包问题
    2. TCP或者其他面向字节流的传输方式都是有一个接收缓冲区的。由于是面向字节流的,所以接收方无法确定从哪开始从哪结束是一个完整的数据报。
    3. 要想解决粘包问题就在应用层协议这里进行区分:只要在定义应用层数据协议的时候,明确包和包之间的“边界”就可以了。
    4. 典型的办法有两种:
      ① 通过分隔符:比如约定使用;作为包的结束标记
      ② 通过指定包的长度:比如在数据报的开头位置声明长度
    5. 缓冲区的作用就是为了提高效率,减少访问I/O的开销
    6. UDP发送的时候也是有缓冲区的,但是不能够向TCP那样进行手动刷新(所以之前其实一直说的是UDP没有发送缓冲区,只有接收缓冲区);接收的时候是有缓冲区的。
    7. 具体代码中如何确定分隔符?(简单了解就行,没时间直接跳过)

    在自定义应用层协议中有几个典型的实现:
    ①XML:分隔符就相当于结束标签
    ②JSON:分隔符就相当于}
    ③Protobuffer:里面通过申明长度的方式来确定边界
    ④HTTP:分隔符和长度两个都会用到

    【TCP中的异常处理】

    1. TCP中的连接如果出现异常,怎么办?
      1)程序崩溃
      ① 相当于进程的异常退出。而程序退出(正常or异常)之后操作系统就会回收进程的资源,包括释放文件描述符表,这样的释放操作就相当于调用了对应socket的close;执行close就会触发FIN报文,进一步开始四次挥手。
      ② 所以该情况与普通的四次挥手没啥区别。

    2)正常关机(通过开始菜单这种方式来关闭主机)
    关机的时候系统会先强制结束所有的用户进程,和上述的进程崩溃类似,系统内核会进行文件描述符表的释放操作,从而进一步进行四次挥手

    3)断电关机(主机掉电)
    非常突然,猝不及防。
    ① 掉电的是接收方,发送方并不知道对面已经挂了,会继续发送数据。
    但是此时发送的数据就没有ACK返回,发送方就会触发超时重传;重传了几次之后仍然没有应答,此时就会尝试重置连接(通过复位报文段),但是也会失败;此时就会直接放弃连接
    【复位报文段其实就是TCP报头中特殊标志位中的RST,为1就是有效的】
    (补充:特殊标志位中:PSH:向对方所要数据,希望对方给个回应; URG:跟紧急指针相关)
    ② 掉电的是发送方,此时接收方就只能等着。
    但是接收方也不是干等,等了一段时间之后就会发送一个“心跳包”,心跳包是周期性触发的,只是一个简单的不携带任何业务数据的包,存在的意义就是确认一下对方是否还在。
    如果对方不返回心跳包,说明此时对方已经挂了。

    4)网线断开
    情况同主机掉电类似,只不过通信双方的主机都正常,这两端各自按照上述两种情况分别进行。

    另(含面试题)

    1. 【TCP和UDP之间各自的应用场景对比】:
      ① TCP使用在有可靠性要求的场景中,使用TCP是非常广泛的。
      ② UDP用在对于可靠性要求不高,但是对于传输效率要求比较高的场景中。如机房内部的内网传输:【不容易丢包:带宽比较充裕,且网络结构相对简单】+【传输效率要求也比较高】

    2. 注:传输层并不是只有TCP和UDP两个协议的,还有其他协议:
      像平时玩的LOL等实时性要求较高的游戏,一般既需要保证可靠性又需要保证效率,所以此时就可以使用KCP(但是不详细介绍)
      3.【常见面试题】——经典
      如何使用UDP来实现可靠传输?
      (主要考查的其实是TCP)
      其实就是基于UDP在应用层来实现确认应答、超时重传、引入序列号、滑动窗口(会确认都收到才滑到下一个)等等。(自己补充完善)

    TCP小结

    1. 为什么TCP这么复杂?因为要保证可靠性,同时又尽可能的提高性能。
      1)可靠性:

    校验和 、序列号(按序到达)、 确认应答、 超时重传、 连接管理(三次握手、四次挥手)、 流量控制、 拥塞控制。

    2)提高性能:

    滑动窗口 、快速重传 、延迟应答 、捎带应答

    3)其他:

    定时器(超时重传定时器,保活定时器,TIME_WAIT定时器等)

    1. 基于TCP应用层协议

    HTTP、 HTTPS、 SSH 、Telnet 、FTP、 SMTP
    当然,也包括你自己写TCP程序时自定义的应用层协议


    THINK

    1. TCP提高传输效率:延迟应答、捎带应答
    2. 面向字节流的“粘包问题”:分隔符、包长度
    3. TCP异常处理:程序崩溃、正常关机、主机掉电、网线断开
      4.== 面试题:如何使用UDP来实现可靠传输?==【确认应答、超时重传、滑动窗口、引入序列号等】(不能使用流量和拥塞控制,因为是UDP是直接进行all发送的)
  • 相关阅读:
    1000 + Java 面试题,26,Javaweb基础知识点
    如何在前端项目中管理依赖关系?
    基于视觉显著性的车载单目相机自运动估计及前车尺度估计方法
    DBA 数据库管理 . 内连接.外链接
    立创EDA软件专业版 图示入门操作(全)
    单元测试实战(四)MyBatis-Plus 的测试
    【万字长文】使用 LSM-Tree 思想基于.Net 6.0 C# 实现 KV 数据库(案例版)
    深入Linux内核理解epoll事件轮询机制
    Servlet
    简单python画图
  • 原文地址:https://blog.csdn.net/weixin_54150521/article/details/128009844