嵌入式面试题 - 网络编程总结(二)

嵌入式面试题 - 网络编程总结(二)


16.IP地址,网关,默认网关,网关地址,子网掩码,DNS

  • IP地址:每个连接到网络的设备在互联网上的逻辑地址,用于标识网络设备

    • IP地址实质是一个32位二进制数,可用十进制表示,由网络号和主机号组成
    • IP地址 = 网络地址 + 主机地址

  • 网关:网关是连接不同网络并转发数据的设备,通常是路由器,负责在本地网络和其他网络之间进行通信

    • 同一网段的设备可以直接通信,而不同网段的设备需要通过网关通信
    • 网关也是具有路由功能的设备的IP地址
  • 默认网关:在一个网络中,当设备(通常是路由器)需要访问其他网络或子网时,发送数据包的默认目标设备的IP地址

    • 主要作用:作为设备访问不同子网或外部网络的出口,确保设备能够与其他网络或互联网进行通信
  • 网关地址:本地网络中用于与外部网络进行通信的路由器的IP地址

    • 网关地址是路由器的IP地址,也是本地网络中的网关设备的IP地址

  • 当本地设备需要访问不同子网或外部网络时,数据包会被发送到网关地址

    • 例如,假设有两个不同子网:

      • 网络1的IP地址范围是 192.168.1.1-192.168.1.254
      • 网络2的IP地址范围是 192.168.2.1-192.168.2.154
    • 这两个网络是不能进行连接通信的,需要通过网关IP地址来进行调节了

    • 为了让它们互通,数据包会通过网关转发:

      • 如果网络1的设备需要访问网络2,它会将数据包发送到网关的IP地址

      • 网关收到数据包后,判断目标地址属于另一个网络,随后将数据包转发到网络2

    • 网关作用:

      • 不同子网之间的通信:同一个子网内的设备可以直接通信,而不同子网的设备需要通过网关进行通信
      • 网关的IP地址:网关的IP地址就是路由器的IP地址,它是一个网络与另一个网络通信的中介,负责转发数据包
      • 路由功能:网关的IP地址指向具备路由功能的设备,
        这些设备能根据路由表将数据包从一个子网或网络转发到另一个子网或网络
    • 同一子网内的设备可以直接通信,无需通过网关;而 不同子网 的设备,通信时必须经过 路由器网关 转发


  • 子网掩码:用来判断任意两台计算机的IP地址是否属于同一子网络的根据

    • IP地址 = 网络地址 + 主机地址
    • 子网掩码是不可缺少的,是用于确定网络位的
    • 网络位:IP地址,前面的某些数字,代表这个主机所在的网段
      • 两台电脑通过比较网络位(网络部分)是否相同判断是否处于同一个网段
  • 子网掩码作用:告诉计算机哪些是网络号,哪些是主机号

  • 例如:192.168.10.1

  • 子网掩码:255.255.255.0:表示IP地址前3段是网络位(网络部分):192.168.10

  • 子网掩码:255.255.0.0: 表示IP地址前2段是网络位(网络部分):192.168


  • DNS:又称域名系统,将人类易记的域名转换为计算机能够识别的IP地址的系统

    • 例:将www.996748.com转换为192.996.1.1(只是举例,不考虑地址是否正确)
      • 家里面的电脑一定会用到域名解析,所以一定会有DNS服务器
      • 即:每台连接互联网的设备都需要通过DNS服务器进行域名解析
    • DNS服务器作用:通过网址来访问目标
      • 你也可以使用IP地址访问网站,例如小破站
      • 有了DNS服务器你就可以不需要去记忆IP地址了,输入网址就可以了
    • DNS原理(域名解析原理):
      • 我们在浏览器输入小破站网址www.bilibili.com
      • 然后你的电脑会把这个网址发到DNS服务器上面,DNS服务器把网址转化为IP地址
      • 电脑访问这个IP地址,打开了小破站

参考:IP地址丨子网掩码丨默认网关丨DNS概念_bilibili


17.如果IPV4地址不够用了怎么办?(如何解决地址荒?)

  • 1.引入IPV6

    • IPv4与IPv6的对比:
      • IPv4:2^4 = 32 位地址,最大提供约42亿个IP地址,已接近耗尽
      • IPv6:2^6 = 128位地址,提供几乎无限的地址空间,可以为每个设备分配独立IP
  • 2.使用NAT(网络地址转换)

    • 至于为什么IPV4已经耗尽,我们似乎没有受到什么影响,是因为IPV4有一个东西叫做NAT(网络地址转换)

    • 如果使用IPV6就可以不使用NAT了,每一户都可以拥有独立的IP地址

    • NAT(网络地址转换)通过修改数据包的源IP地址和端口号,将私有IP地址转为公网IP地址,从而实现内网设备与外网通信

      • 网络分为局域网和广域网,将IP分为了私有IP和公网IP
        • 局域网(LAN) :内网,使用私有IP地址
        • 广域网(WAN):外网,使用公网IP地址
    • 如何减少公网IP消耗?
      NAT允许多个内网设备共享一个公网IP地址,多个设备通过公网IP与外部通信,从而有效地减少公网IP的使用

      • 例如,家庭或公司网络中的多台设备都可以通过一个路由器的公网IP与外界互联网通信,节省了大量的公网IP资源

      • 即:一个局域网里的多台机器都可以共用一个公网IP,从而使可用公网IP数消耗减少

    • NAT的核心作用:让多个内网设备共享一个公网IP地址,避免公网IP地址不足的问题


18.为什么IPV6普及非常难?

  • 1.IPV4和IPV6互不兼容

    • 地址格式差异:IPV4和IPV6完全不同,IPV4使用32位地址,而IPV6使用128位地址,无法直接兼容

    • 协议栈修改:IPV6增加了地址容量,导致了所有IP协议栈都要改变,为了兼容IPV4和IPV6需要两套代码

      • IPV4的协议比作一扇门,如果你要使用IPV6,你就又装了一扇门
    • 硬件支持:IPV6还需要新的硬件支持,成本较高

    • 网址兼容性问题:很多网址是不支持IPV6访问的,网站有兼容,就必须双栈支持,即IPV4和IPV6需要同时兼容


  • 2.安全问题

    • NAT技术虽然提高了被远程访问的难度,但是增加了访问的安全性
    • 网络攻击可以被最外层路由器拦截,同时防火墙也处于这层路由器中

  • 4.利益

  • IPV4动态公网IP申请很难,所以可用卖个好价钱

  • 中国虽然大力推广IPV6的,但是还是有非常多的企业是关闭了IPV6的

参考:IPV4地址早就用完,为何你上网没影响?_哔哩哔哩_bilibili


19.公网,私网,内网,外网

  • 公网:共有网络,人人都可以访问的网络,一般指互联网上的所有网络

    • 所有通过公网IP地址可访问的设备都位于公网中
    • 特点:设备可以通过公网IP地址互相访问,连接全球互联网
  • 私网:私有网络,未经授权无法访问的网络

    • 通常用于公司、家庭等封闭环境中
    • 特点:使用私有IP地址在公网中不可直接访问

  • 内网:内部网络,也加局域网(LAN),使用私有IP地址

    • 特点:设备之间通过私有IP进行通信,通常不直接暴露于外网,需要通过路由器或NAT转换才能访问公网
  • 外网:外部网络,也叫广域网(WAN),使用公网IP地址

    • 外网也指通过公网IP与外部网络连接的部分
    • 特点:外网与内网相对,通常指互联网以及其他远程网络,设备通过公网IP与外网进行通信

20*.为什么我在公司里访问不了家里的电脑?怎么解决?

  • 原因:

  • 那是因为家里的电脑在局域网内,局域网和广域网之间存在一个NAT路由器

  • 由于NAT路由器的存在,外网服务无法主动连通局域网内的电脑


  • NAT(网络地址转换)工作原理:

    • 通过修改数据包的源IP地址和端口号,将私有IP地址转为公网IP地址,从而实现内网设备与外网通信

  • 解决办法:使用内网穿透解决

    • 内网穿透工作原理:

    • 答法1:

    • 内网设备需要主动连接公网服务器,这样NAT路由器就会创建一个端口映射,允许公网服务器通过映射的端口与内网设备通信

    • 公网服务器(比如服务器x)充当中转,内网设备通过与服务器x建立连接,外界可以访问该服务器,
      并通过转发将数据转发到内网设备

    • 所有外部请求通过公网服务器x转发给内网设备,从而实现内网穿透


    • 答法2:

    • 使用了NAT上网,前提得内网设备主动请求公网IP,NAT才能将内网的IP端口转成外网IP端口

    • 公网的机器想主动请求内网设备,就会被拦截在NAT路由器上,

    • 此时由于NAT路由器并没有任何相关的IP端口的映射记录,因此也就不会转发数据给内网里的任何一台设备

    • 所以在公网上加一台服务器x,并暴露一个访问域名,再让内网的服务主动连接服务器x,NAT路由器上就会有对应的映射关系

    • 再然后,所有人都去访问服务器x,服 器x将数据转发给内网机器,再原路返回响应,这样数据就都通了


21*.两个内网的聊天软件(如QQ)如何建立通讯?

  • 这里稍微了解一下,要是面试官都问你这个问题了,基本上就是压力面了


  • 两台机器都在局域网里,且NAT只能从内网连到外网,那我电脑上登录的QQ是怎么和班 花电脑里的QQ连上的呢?

    • 1.客户端主动连接公网服务器
      • 每台客户端在启动并登录QQ时,都会主动连接到QQ的公网聊天服务器
      • 由于客户端与QQ服务器之间的连接是外向连接(由内网客户端发起),NAT路由器会为这个连接在公网端口上建立映射关系,即使客户端在局域网内也不影响连接的建立
    • 2.NAT路由器的端口映射:
      • 当QQ客户端通过NAT路由器连接到公网服务器时,NAT会为每个连接分配一个外部的公网IP和端口号,并记录这个映射关系
      • 这样在公网服务器(QQ服务器)与客户端之间的数据传输就可以顺利进行,因为QQ服务器知道客户端的外部映射IP和端口
    • 3.通过中转服务器转发消息:
      • 由于两个客户端都与QQ服务器建立了连接,服务器便知道两个客户端的公网IP和端口,即使它们分别处于不同的内网中
      • QQ服务器作为中转服务器,负责将客户端A的消息转发给客户端
      • 即使两个客户端的私有IP无法直接互相访问,它们也可以通过QQ服务器进行消息传递
      • 如果两个客户端之间需要建立P2P连接(点对点),例如进行语音通话或视频通话时,
        QQ服务器仍然会充当中转,除非能够通过NAT穿透技术建立直连。
    • 4.NAT穿透技术:
      • 两个在内网的客户端登录qq时都会主动向公网的聊天服务器建立连接,这时两方的NAT 路由器中都会记录有相应的映射关系
      • 对于P2P通讯,若两个客户端都处于NAT后,NAT穿透技术可以帮助客户端建立直接连接
      • 具体来说,STUN协议帮助客户端获取自己在公网的IP和端口信息
      • 而TURN则用作中继服务器,帮助转发数据,确保即使NAT穿透失败,也能通过TURN服务器进行通信。
    • 5.消息传递流程:
      • 当客户端A向客户端B发送消息时,消息会通过QQ服务器转发,
        QQ服务器会根据客户端B的公网IP和端口将消息转发到客户端B
      • 如果两个客户端之间需要直接建立连接(例如视频聊天),客户端A和B会向QQ服务器请求建立P2P连接
      • 若通过STUN/TURN等方式建立了连接,数据会直接在客户端A和B之间传输;
      • 如果不能直接连接,则继续通过QQ服务器中转
  • (至少答出一种,建议答内网穿透,因为简单,为什么使用内网穿透,因为GitHub上面的开源项目可以白嫖节约很多钱


22.IP协议(互联网协议——网络层)

  • IP协议是网络协议中最核心的协议,属于TCP/IP协议栈中的网络层协议,负责数据包的寻址、路由和转发
  • IP协议是互联网中实现设备间通信的基础,提供了设备的标识(IP地址)和数据的传输路径
    • 大部分的上层协议(传输层、应用层)都直接或间接使用IP协议进行数据传输
    • TCP/UDP协议都会依赖IP协议进行数据包的传递
  • 定义:
    • IP协议定义了数据在网络中传输的格式和方式,确保源设备能够通过唯一的IP地址标识目标设备
    • 规定了数据包的封装格式以及如何根据目标IP地址在网络中进行转发
  • IP协议版本:IPV4(32位地址空间)或者IPV6(128位地址空间)
  • IP协议的作用:
    • 1.数据包传输:负责在不同网络之间传递IP数据包
    • 2.寻址与路由:
      • 地址寻址:IP协议为每个设备分配一个唯一的IP地址,确保网络中的每个设备都可以被唯一识别和定位
      • 路由选择:IP协议确定如何在不同网络之间路由数据包。路由器根据目标IP地址决定数据包的转发路径
    • 3.分段与重组(分片传输):如果数据包过大,IP协议会将其分段传输,目标设备会根据分段信息重新组装数据包

23.ICMP协议(互联网控制消息协议) && ping实现原理

  • 作用:用于在网络设备(如路由器和主机)之间传递控制消息

    • 也可以说:用于IP协议中发送控制消息

  • 两大功能:

  • 1.询问报告:询问主机是否可以连通并做出回答(确认IP包是否能够成功到达目标地址)

    • 例如:ping命令
  • 2.差错报告:网络诊断,并且发送诊断报告

    • 比如网关发现目标网络不可达,主机发现访问的UDP端口不可达,需要把错误报告给主机
    • 例如:traceroute

  • ping命令的实现原理(执行过程):

    • 1.记录当前时间

    • 2.构建ICMP报文

    • 3.发生ICMP查询报文

    • 4.接收ICNP回复报文

    • 5.记录当前时间

    • 6.计算延迟时间并且打印在控制台上(终端)

参考:一条视频讲清楚什么是ICMP协议_bilibili


24.ARP协议(地址解析协议),ARP攻击

  • ARP协议:用于将IP地址映射到对应的MAC地址

    • ⭐ARP协议就是通过目标IP地址查询对应的 MAC 地址的协议
    • 工作在OSI模型的数据链路层和网络层之间,是局域网(LAN)中不可或缺的协议之一

  • 工作机制

    • 比喻说明:

      • 邮寄一封包裹,必须有收件人和收件地址
      • 收件人相当于IP地址,收件地址就相当于MAC地址
      • 计算机每发出一包数据,都需要填写4个参数
        • 本机:数据链路层的源MAC
        • ARP协议:目标MAC
        • 用户指定:网络层的源IP,目标IP

  • 答法1:

  • 发送数据的过程:

  • 1.填写数据包的参数

    • 每台计算机发送数据时,都需要填写数据链路层(MAC地址)和网络层(IP地址)相关的4个参数:
    • 本机源MAC地址:数据链路层的源MAC地址
    • ARP协议:用于查询目标设备的MAC地址
    • 网络层的源IP地址:本机的IP地址
    • 目标IP地址:目的设备的IP地址
  • 2.主机A向目标B发送数据

    • 假设计算机A需要向计算机B发送UDP报文:
    • 操作系统将UDP报文缓存,等待目标MAC地址
    • 由于计算机A不知道计算机B的MAC地址,它使用ARP协议查询目标MAC地址
  • 3.ARP请求广播

    • 计算机A会广播一包ARP请求报文,内容包括:
    • 源MAC地址和源IP地址:计算机A的MAC地址和IP地址
    • 目标IP地址:计算机B的IP地址(需要查询MAC地址)
    • 目标MAC地址:初始化为全0,表示没有MAC地址
  • 4.ARP请求的传播和响应

    • 这包ARP请求会在网络中广播,所有网络中的计算机都会接收到该报文
    • 每台计算机会检查目标IP地址,如果目标IP地址与自己的IP地址匹配,表示自己就是目标计算机,应该回复ARP响应报文
  • 5.ARP响应

    • 比如计算机B收到ARP请求后,它会向计算机A回复一包ARP响应报文,内容包括:
    • 目标MAC地址:计算机B的MAC地址
    • 目标IP地址:计算机B的IP地址
    • 计算机A收到ARP响应后,解析出计算机B的MAC地址
  • 6.缓存ARP信息并发送数据

    • 主机A会将目标MAC地址存入ARP缓存(ARP表)中,以便未来的通信不需要再次发送ARP请求
    • 计算机A从缓存中提取目标MAC地址后,将UDP报文填入MAC地址后发送到目标B
  • 7.ARP缓存

    • 目标MAC地址会被存储在主机A的ARP表中,下一次与计算机B通信时,
    • 主机A就可以直接从ARP表中查询到计算机B的MAC地址,而无需再次广播ARP请求

  • 答法2:

  • 假设现在有一台计算机A,需要向目标地址B发送一包UDP报文

  • 此时操作系统会把这一包UDP报文暂时缓存

  • 先用ARP协议去查询对方的MAC地址

  • 主机A会通过网络向外广播一包ARP请求报文

  • 请求报文中,源MAC和源IP都是主机A的MAC和IP,目标IP是需要查询的IP,目标MAC地址是一个全0的MAC地址

  • 这一包请求报文发送后会在网络中广播,网络中的所有计算机都可以收到这一帧请求报文

  • 收到报文的计算机会解析报文,查看目标IP地址,如果和自己的IP地址相同,则说明对这一帧报文应答

  • 比如计算机B收到之后,会回复一包ARP报文,在回复报文中会填入自己的MAC地址

  • 主机A收到回复报文后,会从中解析主机B的MAC地址,并把之前暂存的UDP数据取出,填入MAC地址后做出发出

  • 通过ARP协议查询到的MAC地址会写入到主机的ARP表中,下次发送数据就可以直接从ARP表中查询相关MAC地址


  • ARP攻击:发生ARP攻击后,会导致网络中所有设备都无法正常访问互联网

    • 1.ARP泛洪攻击:通过向网关发送大量ARP报文,导致网关无法正常响应

    • 2.ARP诈骗主机攻击:通过ARP欺骗使得局域网内被攻击主机发送给网关的流量信息实际上都发送给攻击者

    • 3.诈骗网关攻击:把别的主机发送给网关的数据通过欺骗网关的形式使得这些数据通过网关发送给攻击者

    • 4.IP地址冲突攻击:

      通过对局域网中的物理主机进行扫描,扫描出局域网中的物理主机的MAC地址,
      然后根据物理主机的MAC进行攻击,导致局域网内的主机产生IP地址冲突,影响用户的 网络正常使用


    • 这里以欺骗报文为例

    • 假设现在有一个网络,网络中有多台计算机,通过交换机互相通信,同时通过一台路由器连接到了互联网上

    • 其中一台计算机,主机A所有访问互联网的数据包,不管是TCP函数UDP协议,都要通过路由器发送到互联网上

    • 即:在主机A上所有的数据包中,数据链路层的目标MAC地址都是路由器的MAC地址

    • 这个MAC地址也是通过ARP协议查询网关(路由器)的IP

    • 假设现在网络中另一台主机C,一直在网络中广播一包免费ARP报文,这帧报文中伪造了一个IP地址,MAC地址是自己

    • 这包报文发送之后,相当于告诉其他主机,这个IP地址在主机C那里

    • 主机A收到之后,会以为主机C的MAC地址改了,从而去修改自己的ARP表

    • 这样所有正常通信的数据包填写的目标地址就会变成主机C的MAC地址

    • 这些数据包都会被发送到主机C上,从而导致主机A无法正常上网

  • 防御ARP攻击:

    • 这不是我一个学渣该考虑的问题了
    • 最简单的方法是配置静态ARP,将网关IP地址和MAC地址绑定

参考:一条视频讲清楚什么是ARP协议-ARP攻击又是什么_bilibili


==========================

以下全是重点内容

你问为什么目录插进来这么个奇怪的东西?

我的bug不是我说了算,但是我的帖子我说了算

==========================

25.🍁🍀三次握手,四次挥手🍀🍁

说起TCP传输协议,很多人会想到三次握手四次挥手
第一次听感觉好高大上,一定很难吧,然后被网络编程折磨几周之后.......
其实三次握手四次挥手也就是TCP连接的建立(三次握手)和TCP连接的拆除(四次挥手)
最近在博客园看到一篇TCP讲得非常生动形象的帖子,非常有意思(虽然Wireshark软件不会用。。。。。)
再结合一个之前在B站收藏夹吃灰的视频,应该可以帮忙你有更好的 一预习一 认识或者回顾


  • 三次握手(目的:在不可靠的信道上建立可靠的连接):

    • 客户端叫它为老板A,服务器叫它为同事B

    • A:小B啊,听得到吗?

    • B:老板啊,听得到!

    • A:听得到就好,听得到就好啊,刚刚你下班的时候忘记说了,周末记得加班


  • SYN:同步位,表示连接请求

  • ACK:确认位,=1有效,=0无效

  • 答法1

    • 1.当客户端向服务端发起连接时,会先发一包连接请求数据过去询问一下:我能否与你建立连接

      • 这包数据我们称为SYN包
      • 这是第一次握手
    • 2.如果服务器同意连接,则回复一包SYN+ACK包

      • 这是第二次握手

      • [!NOTE]

        第二次握手传回了ACK,为什么还要传回SYN?

        • ACK 是为了告诉客户端传来的数据已经接收无误

        • SYN是为了告诉客户端,服务端响应的确实是客户端发送的报文


        • 即:在第二次握手时,服务器必须传回SYN和ACK,
          以完成双向确认:不仅确认客户端的请求,还表达自己希望建立连接的意图

        • 如果只有ACK,没有SYN,客户端无法知道服务器是否准备好建立连接

    • 3.客户端收到之后回复一包ACK包

      • 这是第三次握手
    • 4.最后建立连接

    • 因为建立连接的过程中互相发送了3包数据,所以叫做三次握手


  • 答法2

  • 三次握手其实就是TCP建立连接的过程

  • 1.第一次握手:SYN

    • 客户端发送一个SYN(同步序列编号)包到服务器,表示客户端希望建立连接,并且客户端进入SYN_SEND状态
  • 2.第二次握手:SYN-ACK

    • 服务器收到SYN包后,返回一个SYN-ACK包,表示同意连接,并且服务器进入SYN_RECV状态
  • 3.第三次握手:ACK

    • 客户端收到SYN-ACK包后,发送一个ACK包确认连接,
    • 并且客户端进入ESTABLISHED状态,服务器也进入ESTABLISHED状态,此时,连接建立完成

  • 四次挥手(目的:在不可靠的网络链路中上进行可靠的连接断开):

    • 你女朋友:我们分手吧
    • 你:现在不行,在打游戏呢
      很长一段时间之后
    • 你:我打完了,你刚刚说什么来着,好像是......分手?
    • 你女朋友:分!手!吧!(恭喜你已分手成功)

  • 答法1:

    • 处于连接状态的客户端和服务端都可以发起关闭连接请求,此时就需要四次挥手来进行连接关闭
    • 假设客户端主动发起连接关闭请求,需要将服务端发起一包FIN包,表示要关闭连接,自己进入终止等待1状态
    • 这是第一次挥手
    • 服务端收到FIN包,发送一包ACK包,表示自己进入了关闭等待状态,客户端进入终止等待2状态
    • 这是第二次挥手
    • 服务端此时还可以发送未发送的数据,而客户端还可以接收数据
    • 待服务器发送完数据之后,发送一包FIN包进入最后确认状态
    • 这是第三次挥手
    • 客户端收到之后回复ACK包,进入超时等待状态,经过超时时间后关闭连接
    • 而服务端收到ACK包后,立即关闭连接
    • 这是第四次挥手

  • 答法2:

  • 四次挥手也就是TCP断开连接的过程

  • 1.第一次挥手:FIN

    • 主动关闭连接的一方(通常是客户端)发送一个FIN包,表示希望断开连接
    • 此时,客户端进入FIN_WAIT_1状态
  • 2.第二次挥手:ACK

    • 接收方(通常是服务器)收到FIN包后,返回一个ACK包,确认关闭请求
    • 此时,服务器进入CLOSE_WAIT状态,客户端进入FIN_WAIT_2状态
  • 3.第三次挥手:FIN

    • 服务器准备关闭连接时,发送一个FIN包,表示关闭连接
    • 此时,服务器进入LAST_ACK状态,客户端收到后进入TIME_WAIT状态
  • 4.第四次挥手:ACK

    • 客户端收到FIN包后,返回一个ACK包,

    • 服务器进入CLOSED状态,客户端在等待一定时间后也进入CLOSED状态,完成断开

参考:Wireshark的TCP包详解 -下篇 - 北京-宏哥 - 博客园 && TCP协议与UDP协议 - 三次握手与四次挥手_bilibili


26.TCP 握手为什么是三次,为什么不能是两次?不能是四次?

  • 为什么是三次握手而不是两次握手?

    • 答法1:

    • 服务器回复完SYN+ACK之后就建立连接,这是为了防止已失效的请求报文突然又传到服务器运气错误

    • 假如采用2次握手建立连接

    • 客户端向服务器发送了一个SYN包来请求建立连接

    • 因为某些未知的原因,并没有到达服务器,在中间某个网络节点产生了滞留

    • 为了建立连接客户端会重发SYN包

    • 这次的数据包正常送达,服务器回复SYN+ACK包之后建立了连接

    • 但是第一包数据阻塞的网络节点突然恢复,第一包SYN又送达到服务端

    • 这时服务端会误以为客户端又发起了新的连接,从而在建立连接之后进入等待数据状态

    • 即:服务器认为是2个链接,客户端认为是1次连接,造成了状态不一致

    • 如果在三次握手的情况下,服务端收不到最后的ACK包,自然不会认为建立成功

    • 所以三次握手本质上来说,就是为了解决网络信道不可靠的问题,即:在不可靠的信道上建立可靠的连接

    • (或者说,三次握手是一个平衡过程,它确保了双方都准备好并且能够确认对方的意图,同时避免了不必要的开销


    • 答法2:

    • 如果只进行两次握手,客户端不能确认服务器是否准备好接收数据

    • 因为在第二次握手中服务器只是确认了自己收到了客户端的请求,但没有明确告诉客户端它已经准备好连接


  • 为什么三次握手不是4次?

    • 四次握手增加了一次额外的确认步骤,虽然没有问题,但增加了开销

    • 三次握手已经足以建立起可靠的连接了,没有必要再进行一次连接了

    • 第四次,只会画蛇添足,导致不必要的延迟和负担

参考:TCP协议与UDP协议 - 三次握手与四次挥手_bilibili


27.三次握手中每一次握手分别没收到报文会发生什么情况?

  • 第一次握手:客户端发送SYN包

    • 发送情况:客户端发送SYN包请求建立连接
    • 如果服务器没有收到SYN包
      • 服务器无法回应给客户端SYN-ACK包
      • 客户端会在一定时间内等待回应(通常是通过重传机制,也就是客户端重新发送SYN包)
      • 如果发送次数超过最大重传次数限制仍未收到服务器的响应,客户端会放弃连接请求,并抛出超时错误

    2. 第二次握手:服务器发送SYN-ACK包

    • 发送情况:服务器收到客户端的SYN包后,发送SYN-ACK包作为回应
    • 如果客户端没有收到SYN-ACK包
      • 客户端无法确认服务器是否接受连接请求,连接无法建立
      • 客户端会继续重传其SYN包,直到达到次数限制或者超时
        • 如果达到次数或者超时,则连接建立失败
      • 服务器端如果没有接收到客户端的SYN包,则无法启动后续的连接确认过程
      • 服务器会继续保持在监听状态,等待客户端的连接请求

    3. 第三次握手:客户端发送ACK包

    • 发送情况:客户端收到服务器的SYN-ACK包后,发送ACK包确认连接建立
    • 如果服务器没有收到ACK包
      • 服务器无法确认客户端已经收到并接受了其SYN-ACK包,因此连接无法确认建立
      • 服务器会继续等待客户端的ACK包,并可能进行重传,直到收到确认或超时

28.TCP 四次挥过程中,为什么客户端需要等待超时时间(2MSL)才能进入 closed 关闭状态?为什么等待的时间是2MSL?

  • 为什么四次挥手中,客户端需要等待超时时间(才可以进入关闭状态)?

    • 这是为了保证对方已经收到ACK包

      • 因为假设客户端发送完最后一包ACK包后就释放了连接
      • 一旦ACK包在网络中丢失,服务端将一直停留在最后确认状态
    • 如果客户端发送最后一包ACK包后等待一段时间

      • 这时因为服务端没有收到ACK包,会重新发送FIN包
      • 客户端会响应FIN包重发ACK包并刷新超时时间
    • 所以四次挥手本质上来说目的也是,在不可靠的网络链路中上进行可靠的连接断开


  • 术语解释:

    • MSL,最大段生存时间,指TCP分段在网络中存活的最大时间,通常被设置为2分钟(120秒)

    • 只不过我还是喜欢叫它报文最大生存时间,它定义了一个TCP数据包(数据段)在网络中能够存活的最长时间

    • 人话: MSL是任何报⽂在⽹络上存在的最⻓时间,超过这个时间报⽂将被丢弃

    • 又到了喜闻乐见的教材不说人话时间了


  • 为什么等待的时间是2MSL?

    • 1.保证所有数据包传输完成(确保最后的ACK包被服务器接收)

      • 在四次挥手的最后,客户端发送一个ACK包来确认收到服务器的FIN包
      • 由于网络中可能存在延迟或丢失的数据包,通过等待2MSL时间,
        客户端能够确保服务器收到并确认最后的ACK包,确保双方都完成连接断开过程
      • 一来一回1MSL * 2 = 2MSL
    • 1.避免重传(确保网络中滞留的旧数据包被丢弃,避免干扰新连接)

      • 如果在断开连接后立即关闭连接,某些报文可能会被网络延迟或重传
      • 如果不等待2MSL的时间,可能会导致这些延迟的报文与新连接的报文混淆,造成误判或连接状态混乱

    • 2MSL的合理性(为什么不能是1MSL或者3MSL)

      • 1MSL不够长,可能导致未完全传输的报文仍在网络中
      • 3MSL过长,浪费资源和时间
      • 2MSL既能确保报文消失,又不会不必要地延长等待

参考:TCP协议与UDP协议 - 三次握手与四次挥手_bilibili


29.TCP的滑动窗口机制与拥塞控制

  • TCP滑动窗口:

    • TCP的滑动窗口机制是一个流量控制机制

    • 它允许发送方在等待确认的同时,发送多个数据段,而不是一个接一个地等待确认

    • (多个数据包打包在一起就有了一个数据段)

    • 滑动窗口确保了TCP连接中双方数据传输的高效性和可靠性


    • 窗口大小

      • 接收方通过TCP头部的Window字段告诉发送方它的缓冲区还能接收多少字节数据
      • 窗口大小可以动态变化
    • 滑动窗口

      • 发送方在发送数据时会根据接收方的窗口大小限制来决定一次可以发送的数据量
      • 当接收方确认收到一定量的数据后,窗口向前滑动,允许发送方继续发送新的数据
    • 流量控制:滑动窗口机制是流量控制的一种形式,防止发送方超速发送数据,以免接收方的缓冲区溢出

    • 工作原理

      • 发送方根据接收方的窗口大小发送数据
      • 每次收到确认(ACK)后,发送方根据新的窗口大小继续发送
      • 窗口滑动的过程取决于接收方的确认和缓冲区空间
    • 举例说明

      • 假设接收方窗口为1000字节,发送方窗口为100字节(每次发送数据段时,会动态调整窗口大小
        • 1.发送方发送100字节数据
        • 2.发送方等待接收方确认(ACK)
        • 3.接收方确认并更新接收窗口
        • 4.发送方收到ACK后,再发送最多100字节数据
        • 5.重复过程直到数据传输完成
      • 总的来说:发送方的发送窗口限制了每次发送的数据量,即使接收方能接收更多数据

  • TCP拥塞控制:

    • TCP的拥塞控制是为了防止网络中发生过度拥塞,导致数据包丢失、延迟增大和网络性能下降
    • 目的:动态调整发送数据的速率,避免网络发生严重拥塞,同时保证高效的带宽利用
    • 原理(四大机制):
      • 慢启动:连接初期,窗口大小迅速增长,直到达到阈值
      • 拥塞避免:窗口大小线性增长,避免过度拥塞
      • 快速重传:收到三个重复ACK时,立即重传丢失的数据包
      • 快速恢复:丢包后减少窗口大小,避免回到慢启动阶段
    • 拥塞窗口和接收窗口共同决定实际发送窗口大小,确保网络稳定性和高效利用带宽

30.TCP粘包问题怎么解决?

// 粘包问题处理及Json解析
// 这是一个线程函数
void ClientRunnable::handleJsonSlot(QTcpSocket &socket)
{
    auto Content = socket.readAll();    	// 读出缓冲区中所有的数据
    buffer.append(Content);             	// 放入我们自己的缓冲区(人造缓冲区)
    while(buffer.size() > sizeof(size_t))   // 缓冲区的数据量大于包头
    {
        size_t size = 0;
        memcpy(&size, buffer.data(), sizeof(size_t));   // 将包头数据取出(内存拷贝)
        // 缓冲区数据量不足以解析一个数据(json)包
        if(buffer.size() < size + sizeof(size_t))
        {
            break;  // 等待下一次缓冲区里的数据
        }
        // 如果够了(提取了完整数据包内容)
        auto data = buffer.mid(sizeof(size_t), size);
        // json解析(业务代码)
        // 工厂+策略模式
        // (不给你看)

        // 从缓冲区中删除这个被解析过的数据包(移除已处理的数据包)
        buffer.remove(0, size + sizeof(size_t));
    }
}

方便理解,这里用一个我之前做过的QT项目中的一小段函数举例,开袋即食,结合代码食用更佳


  • 粘包:当多个数据包合并成一个包进行接收时,接收端无法区分出哪些部分属于哪个原始数据包

  • 要处理TCP粘包问题,我们首先要知道,为什么会出现粘包问题

    • TCP是面向连接,字节流的协议,数据被当作一个连续的字节流进行传输

    • 不同的数据包在网络中传输时,TCP并不会关心每个数据包的边界,
      而是按照字节流的方式将数据分割成多个段发送,接收端也会以字节流的形式接收数据

    • 这种特性可能导致数据包之间的边界不清楚,从而产生粘包问题


  • 人话:

    • 粘包:粘包粘包,数据包就好比两颗糖粘在一起了,你无法分清楚哪一部分是哪个糖的了
    • 为什么会有粘包问题?
      • 是TCP数据传输不可靠?不不不,是你不可靠,TCP是可靠的,是你不可靠的,
        别人TCP每次传输等长字节好端端的,你干嘛要传输不等长数据,
        你不传输不等长数据不就行了.........
        你以为是我不想传输不等长数据吗,但是谁家发消息可以每次发一样的字数啊喂
        本来就是TCP自己的特性问题好不好,假设一包数据可以传输n字节
        第一次发送了 “必修课选逃”,第二次发送了 “选修课必逃”,
        你以为TCP会一次一次发送数据,先发 “必修课选逃”
        但是TCP觉得我缓冲区都没有满啊,我有n个字节啊,我发什么发
        然后它发现刚好把第二次数据填进去刚好合适,
        于是两次发送的数据就一次性全部发送了
        这就是粘包

  • 解决方法:接收和发送均使用包头+数据包的格式发送和接收数据
    • 即:先接收数据包大小, 再通过数据包大小知道要接收的数据长度, 最后接收数据
    • 1.将读取的TCP数据数据添加到自定义缓冲区
    • 2.根据数据包的头部大小(sizeof(size_t))判断是否有完整的数据包
    • 3.如果缓冲区数据足够解析一个包,则提取包内容并进行数据包处理(如JSON解析和业务处理)
    • 4.解析完成后,从缓冲区中移除已处理的数据包

终于终于终于终于整理完了,当初学网络的时候一堆知识点再追我,现在还在追我
当初学网络编程小破站和博客园都快被我翻烂了都没有搞明白
后来在项目里面被按在墙角摩擦几周之后,终于有一点感悟
学习完网络编程和系统编程,我只想吐槽:
腾讯你什么时候把你那个微信的破同步搞好啊,晚上等拼好饭,延迟了半个小时我才收到*……@#……@&@
有时候真想直接来一篇纯吐槽文
最后再叠个甲:博主只是一个即将成为社畜的苦逼大学生,水平有限,
以上问题全是根据自己现有的理解,结合以前的笔记,然后查询大量的资料
最后自己一个人整理,总结出来的,可能会有些许错误,如果存在一些问题,还望各位可以指出
最后再祝愿看的各位可以在来年找到好工作

posted @ 2025-01-08 21:48  假设狐狸有信箱  阅读(130)  评论(0)    收藏  举报