网络互联模型

为了更好地促进互联网络的研究和发展,国际标准化组织ISO在1985年制定了网络互连模型,OSI参考模型(Open System Interconnect Reference Model),具有7层结构

image-20220627163134014

数据请求过程

image-20220627163258767

分层数据

image-20220627164415406

物理层

物理层定义了接口标准、线缆标准、传输速率、传输方式等

数字型号,模拟信号

模拟信号(Analog Signal):连续的信号,适合长距离传输,抗干扰能力差,受到干扰时波形变形很难纠正
数字信号(Digital Signal):离散的信号,不适合长距离传输,抗干扰能力强,受到干扰时波形失真可以修复

数据通信模型

image-20220627164930362

信道

信道:信息传输的通道,一条传输介质上(比如网线)上可以有多条信道
单工通信:信号只能往一个方向传输,任何时候都不能改变信号的传输方向1比如无线电广播、有线电视广播
半双工通信:信号可以双向传输,但必须是交替进行,同一时间只能往一个方向传输l比如对讲机
全双工通信:信号可以同时双向传输,比如手机(打电话,听说同时进行)

数据链路层

链路:从1个节点到相邻节点的一段物理线路(有线或无线),中间没有其他交换节点

image-20220628093423815

数据链路:在一条链路上传输数据时,需要有对应的通信协议来控制数据的传输不同类型的数据链路,所用的通信协议可能是不同的

广播信道:CSMA/CD协议比如同轴电缆、集线器、交换机等组成的网络,两个路由器之间如果有交换机等设备的话,走的也是这个协议)

点对点信道:PPP协议(比如2个路由器之间的信道)

数据链路层的3个基本问题:封装成帧、透明传输、差错检验

封装成帧

帧(Frame)的数据部分就是网络层传递下来的数据包(IP数据包,Packet)

最大传输单元MTU (Maximum Transfer Unit):每一种数据链路层协议都规定了所能够传送的帧的数据长度上限以太网的MTU为1500个字节

透明传输

image-20220628094051494

使用SOH (Start Of Header)作为帧开始符
使用EOT (End Of Transmission)作为帧结束符

数据部分一旦出现了SOH、EOT,就需要进行转义

image-20220628094220603

ESC如果不转义,就会去就会把当前ESC的相邻字符当成特殊字符;把ESC转义的原因和EOT及SOH一样,都是为了将其直接当成普通数据接收。

差错检验

image-20220628095704382

FCS是根据数据部分+首部计算得出的

CSMA/CD协议

CSMA/CD (Carrier Sense Multiple Access with Collision Detectio):载波侦听多路访问/冲突检测

使用了CSMA/CD的网络可以称为是以太网(Ethernet),它传输的是以太网帧以太网帧的格式有: Ethernet V2标准、IEEE的802.3标准
使用最多的是:Ethernet V2标准

为了能够检测正在发送的帧是否产生了冲突,以太网的帧至少要64字节

帧要足够长,才能在发生冲突时知道发生冲突的帧是哪个。否则发生冲突时该帧已经全部发出,将无法进行判断。不够64字节会自动填充。

用交换机组建的网络,已经支持全双工通信,不需要再使用CSMA/CD,但它传输的帧依然是以太网帧
所以,用交换机组建的网络,依然可以叫做以太网

【Ethernet V2标准帧格式】

image-20220628104632504

数据部分最少为46字节即,64字节减去了MAC地址等其他数据18字节。

最多为1500字节即MTU最大为1500字节。

当数据部分的长度小于46字节时
数据链路层会在数据的后面加入一些字节填充,接收端会将添加的字节去掉

image-20220628110144703

【长度总结】

以太网帧的数据长度:46~1500字节
以太网帧的长度:64~1518字节(源MAC+目标MAC+网络类型+数据+FCS)

PPP协议

PPP协议(Point to Point Protocol)

image-20220628110454224

Address字段:图中的值是0xFF,形同虚设,点到点信道不需要源MAC、目标MAC地址

Control字段:图中的值是0x03,目前没有什么作用

Protocol字段:内部用到的协议类型

帧开始符、帧结束符:0x7E

网卡

image-20220628114111871

网卡接收到一个帧,首先会进行差错校验,如果校验通过则接收,否则丢弃
Wireshark抓到的帧没有FCS,因为它抓到的是差错校验通过的帧(帧尾的FCS会被硬件去掉)

集线器可以看成网线,所以是一个物理层设备(只能接触到比特流)。

交换机是一个二层设备,需要看源MAC和目标MAC(可以接触到帧数据)。

路由器是三层设备,需要看IP地址(可以接触到包数据)。

网络层

网络层数据包(IP数据包,Packet)由首部、数据2部分组成

数据:很多时候是由传输层传递下来的数据段(Segment)
image-20220628115618505

  • 版本(Version)占4位
    0b0100: IPv4
    0b0110: IPv6

  • 首部长度(Header Length)
    占4位,二进制乘以4(一行四个字节,固定部分5行,5×4 = 20)才是最终长度
    0b0101: 20(最小值)
    0b1111: 60(最大值,也就是说可选部分最多40字节)

  • 区分服务(Differentiated Services Field)
    占8位,可以用于提高网络的服务质量(QOS,Quality of Service)

    例如,路由器可以让某些含有特定区分服务的数据优先通过。

  • 总长度(Total Length)占16位
    首部+数据的长度之和,最大值是65535image-20220628143246326

  • 由于帧的数据不能超过1500字节,所以过大的IP数据包,需要分成片(fragments)传输给数据链路层,每一片都有自己的网络层首部(IP首部)

  • 标识(ldentification)

    • 占16位
    • 数据包的ID,当数据包过大进行分片时,同一个数据包的所有片的标识都是一样的
    • 有一个计数器专门管理数据包的ID,每发出一个数据包,ID就加1(循环,用完后重新开始)
  • 标志(Flags)

    • 占3位
    • 第1位(Reserved Bit)∶保留
    • 第2位(Don't Fragment) : 1代表不允许分片,0代表允许分片
    • 第3位(More Fragments) :1代表不是最后一片,0代表是最后一片
  • 片偏移(Fragment Offset)

    • 占13位
    • 片偏移乘以8:字节偏移
    • 每一片的长度—定是8的整数倍
image-20220628143908943

【相关命令用法】

ping /? //查看ping的用法
ping ip地址 -l 数据包大小 //发送指定大小的数据包
ping ip地址 -f //不允许网络层分片
ping ip地址 -i TTL //设置TTL的值
通过tracert、pathping命令,可以跟踪数据包经过了哪些路由器

  • 生存时间(Time To Live,TTL)占8位
    每个路由器在转发之前会将TTL减1,一旦发现TTL减为0,路由器会返回错误报告观察使用ping命令后的TTL,能够推测出对方的操作系统、中间经过了多少个路由器

    image-20220628162541637
  • 协议(Protocol)占8位
    表明所封装的数据是使用了什么协议

image-20220628162615700
  • 首部校验和(Header Checksum)
    用干检查首部是否有错误

关于ARP协议应该置于那一层:

 arp协议在TCP/IP模型中属于IP层(网络层),在OSI模型中属于链路层。arp协议即地址解析协议,是根据IP地址获取物理地址的一个TCP/IP协议。它可以解决同一个局域网内主机或路由器的IP地址和MAC地址的映射问题。

传输层

TCP ( Transmission Control Protocol),传输控制协议

UDP (User Datagram Protocol),用户数据报协议

image-20220628171113408

UDP协议

UDP是无连接的,减少了建立和释放连接的开销

UDP尽最大能力交付,不保证可靠交付

因此不需要维护一些复杂的参数,首部只有8个字节(TCP的首部至少20个字节)

image-20220628171601116
  • UDP长度(Length)
    占16位,首部的长度+数据的长度

  • 检验和的计算内容:伪首部+首部+数据
    伪首部:仅在计算检验和时起作用,并不会传递给网络层

    image-20220630091146412
  • 端口

    可以推测出端口号的取值范围是:0~65535

    • 客户端的源端口是临时开启的随机端口
    • 防火墙可以设置开启\关闭某些端口来提高安全性
    • 常用命令行
      • netstat –an:查看被占用的端口
      • netstat –anb:查看被占用的端口、占用端口的应用程序
      • telnet 主机 端口:查看是否可以访问主机的某个端口
      • 安装telnet:控制面板 – 程序 – 启用或关闭Windows功能 – 勾选“Telnet Client” – 确定
image-20220630091624287

TCP协议

image-20220630093521861
  • 数据偏移(首部长度)
    • 占4位,取值范围是0x0101~0x1111
    • 乘以4:首部长度(Header Length)
    • 首部长度是20~60字节
  • 保留:占6位,目前全为0(也有资料说保留位为三位,标志位为9位,但实际上标志位中有三位是不常用的)

UDP的首部中有个16位的字段记录了整个UDP报文段的长度(首部+数据)
但是,TCP的首部中仅仅有个4位的字段记录了TCP报文段的首部长度,并没有字段记录TCP报文段的数据长度

【分析】
UDP首部中占16位的长度字段是冗余的,纯粹是为了保证首部是32bit对齐TCP\UDP的数据长度,完全可以由IP数据包的首部推测出来

  • 传输层的数据长度=网络层的总长度–网络层的首部长度–传输层的首部长度
  • 校验和

    跟UDP一样,TCP检验和的计算内容:伪首部+首部+数据
    伪首部:占用12字节,仅在计算检验和时起作用,并不会传递给网络层

  • 标志位

    • URG (Urgent)
      当URG=1时,紧急指针字段才有效。表明当前报文段中有紧急数据,应优先尽快传送

    • ACK (Acknowledgment)
      当ACK=1时,确认号字段才有效

    • PSH (Push)

      一般用不上

    • RST (Reset)
      当RST=1时,表明连接中出现严重差错,必须释放连接,然后再重新建立连接

    • SYN (Synchronization)
      当SYN=1、ACK=0时,表明这是一个建立连接的请求若对方同意建立连接,则回复SYN=1、ACK=1

    • FIN (Finish)
      当FIN=1时,表明数据已经发送完毕,要求释放连接

  • 序号(Sequence Number)占4字节
    首先,在传输过程的每一个字节都会有一个编号
    在建立连接后,序号代表:这一次传给对方的TCP数据部分的第一个字节的编号

  • 确认号(Acknowledgment Number)
    占4字节
    在建立连接后,确认号代表:期望对方下一次传过来的TCP数据部分的第一个字节的编号

  • 窗口(Window)
    占2字节
    这个字段有流量控制功能,用以告知对 方下一次允许发送的数据大小(字节为单位)

可靠传输

停止等待ARQ协议

image-20220630154116044 image-20220630154126819

若有个包重传了N次还是失败,会一直持续重传到成功为止么?
这个取决于系统的设置,比如有些系统,重传5次还未成功就会发送reset报文(RST)断开TCP连接

image-20220630154501886

连续ARQ协议+滑动窗口协议

image-20220630154644351

如果接收窗口最多能接收4个包但发送方只发了2个包
接收方如何确定后面还有没有2个包?

等待—定时间后没有第3个包
就会返回确认收到2个包给发送方——这样发送方就可以看是传完了,丢失了还是怎么回事

TCP01_序号_确认号

SACK(选择性确认)

在TCP通信过程中,如果发送序列中间某个数据包丢失(比如1、2、3、4、5中的3丢失了)TCP会通过重传最后确认的分组后续的分组(最后确认的是2,会重传3、4、5)
这样原先已经正确传输的分组也可能重复发送(比如4、5),降低了TCP性能

为改善上述情况,发展出了SACK (Selective acknowledgment,选择性确认)技术告诉发送方哪些数据丢失,哪些数据已经提前收到
使TCP只重新发送丢失的包(比如3),不用发送后续所有的分组(比如4、5)

SACK信息会放在TCP首部的选项部分:

  • Kind:占1字节。值为5代表这是SACK选项
  • Length:占1字节。表明SACK选项一共占用多少字节
  • Left Edge:占4字节,左边界
  • Right Edge:占4字节,右边界
image-20220630160131439 image-20220630160452804

一对边界信息需要占用8字节,由于TCP首部的选项部分最多40字节,所以SACK选项最多携带4组边界信息
SACK选项的最大占用字节数=4*8+2 =34 (kind和length为刚需)

为什么选择在传输层就将数据“大卸八块”分成多个段,而不是等到网络层再分片传递给数据链路层?

因为可以提高重传的性能
需要明确的是:可靠传输是在传输层进行控制的
如果在传输层不分段,一旦出现数据丢失,整个传输层的数据都得重传;如果在传输层分了段,一旦出现数据丢失,只需要重传丢失的那些段即可(UDP不具备重传功能,所以是在网络层分段的)

流量控制

  • 如果接收方的缓存区满了,发送方还在疯狂着发送数据
    接收方只能把收到的数据包丢掉,大量的丢包会极大着浪费网络资源所以要进行流量控制
  • 什么是流量控制?
    让发送方的发送速率不要太快,让接收方来得及接收处理
  • 原理
    通过确认报文中窗口字段来控制发送方的发送速率发送方的发送窗口大小不能超过接收方给出窗口大小
    当发送方收到接收窗口的大小为0时,发送方就会停止发送数据

有一种特殊情况
一开始,接收方给发送方发送了0窗口的报文段
后面,接收方又有了一些存储空间,给发送方发送的非0窗口的报文段丢失了发送方的发送窗口一直为零,双方陷入僵局

解决方案
当发送方收到0窗口通知时,这时发送方停止发送报文
并且同时开启一个定时器,隔一段时间就发个测试报文去询问接收方最新的窗口大小如果接收的窗口大小还是为0,则发送方再次刷新启动定时器

拥塞控制

image-20220701090339191
  • 拥塞控制
    防止过多的数据注入到网络中,避免网络中的路由器或链路过载
  • 拥塞控制是一个全局性的过程涉及到所有的主机、路由器
    以及与降低网络传输性能有关的所有因素
  • 是大家共同努力的结果
  • 相比而言,流量控制是点对点通信的控制

解决方案:

  • 慢开始(slow start,慢启动)
  • 拥塞避免 (congestion avoidance)
  • 快速重传(fast retransmit)
  • 快速恢复( fast recovery)

【几个缩写】

MSS (Maximum Segment Size) :每个段最大的数据部分大小在建立连接时确定(在可选字段发送,所以建立连接时不仅使用了20固定字节,还使用了可选字段,此时一般头部总长为32字节)
cwnd (congestion window):拥塞窗口
rwnd (receive window):接收窗口
swnd (send window):发送窗口swnd = min(cwnd, rwnd)

慢开始

image-20220701105149914

cwnd的初始值比较小,然后随着数据包被接收方确认(收到一个ACK),cwnd就成倍增长(指数级)

拥塞避免

image-20220701105438090
  • ssthresh (slow start threshold):慢开始阈值,cwnd达到阈值后,以线性方式增加

  • 拥塞避免(加法增大)︰拥塞窗口缓慢增大,以防止网络过早出现拥塞

  • 乘法减小:只要网络出现拥塞,把ssthresh减为拥塞峰值的一半,同时执行慢开始算法(cwnd又恢复到初始值)

  • 当网络出现频繁拥塞时,ssthresh值就下降的很快

快重传

  • 接收方
    每收到一个 的分组后就立即发出重复确认使发送方及时知道有分组没有到达
    而不要等待自己发送数据时才进行确认(之前的做法是等到自己发数据的时候一并确认前面收到的
  • 发送方
    只要连续收到三个重复确认(总共4个相同的确认),就应当立即重传对方尚未收到的报文段而不必继续等待重传计时器到期后再重传

快恢复

  • 当发送方连续收到三个重复确认,说明网络出现拥塞
    就执行“乘法减小”算法,把ssthresh减为拥塞峰值的一半
  • 与慢开始不同之处是现在不执行慢开始算法,即cwnd现在不恢复到初始值而是把cwnd值设置为新的ssthresh值(减小后的值)
    然后开始执行拥塞避免算法(“加法增大”),使拥塞窗口缓慢地线性增大

==快重传 + 快恢复==

image-20220701135129102

发送窗口的最大值: swnd = min(cwnd, rwnd)
当rwnd < cwnd时,是接收方的接收能力限制发送窗口的最大值
当cwnd < rwnd时,则是网络的拥塞限制发送窗口的最大值

序号及确认号

image-20220704101614577 image-20220704112035233

前三次握手数据部分都为0,即便第三次握手时seq字段为1,亦是如此。

image-20220704113708699

image-20220704114218102 image-20220704121825832 TCP04_序号确认号01_相对 TCP05_序号确认号02_原生

需要注意的是:序号并非1、2、3……这种简单的数值,而是一个很大的数值,这样做可以防止中间人截取到数据包后轻易知道数据包序号;而这个较大地数值是在建立连接时进行确定地。另外,通信双方在建立连接时都会发送自己地序号,这两个序号不一定相同。

在后面的通信过程中,都是在原序号的基础上进行加一操作。

三次握手

image-20220704122147644

【上述状态解释】

CLOSED: client处于关闭状态
LISTEN: server处于监听状态,等待client连接
SYN-RCVD:表示server接受到了SYN报文,当收到client的ACK报文后,它会进入到ESTABLISHED状态
SYN-SENT:表示client已发送SYN报文,等待server的第2次握手
ESTABLISHED:表示连接已经建立

【前两次握手要点】

  • SYN都设置为1
  • 数据部分的长度都为0
  • TCP头部的长度一般是32字节
    • 固定头部:20字节
    • 选项部分:12字节
  • 双方会交换确认一些信息
    比如MSS、是否支持SACK、Window scale(窗口缩放系数)等这些数据都放在了TCP头部的选项部分中(12字节)

【为什么两次握手不行】

  • 为什么建立连接的时候,要进行3次握手?2次不行么?
    主要目的:防止server端一直等待,浪费资源
  • 如果建立连接只需要2次握手,可能会出现的情况
    假设client发出的第一个连接请求报文段,因为网络延迟,在连接释放以后的某个时间才到达server
    本来这是一个早已失效的连接请求,但server收到此失效的请求后,误认为是client再次发出的一个新的连接请求于是server就向client发出确认报文段,同意建立连接
    如果不采用“3次握手”,那么只要server发出确认,新的连接就建立了
    由于现在client并没有真正想连接服务器的意愿,因此不会理睬server的确认,也不会向server发送数据但server却以为新的连接已经建立,并一直等待client发来数据,这样,server的很多资源就白白浪费掉了
  • 采用“三次握手”的办法可以防止上述现象发生
    例如上述情况,client没有向server的确认发出确认,server由于收不到确认,就知道client并没有要求建立连接
  • 此外,等待的那一方是可以设置socket的自动关闭时间的,如果有数据包过来的话刷新这个时间(keep-alive,HTTP也有这个概念,但不同)
  • 第3次握手失败了,会怎么处理?
    此时server的状态为SYN-RCVD,若等不到client的ACK,server会重新发送SYN+ACK包如果server多次重发SYN+ACK都等不到client的ACK,就会发送RST包,强制关闭连接

释放连接

image-20220704163406492

TCP/IP协议栈在设计上,允许任何一方先发起断开请求。这里演示的是client主动要求断开

client发送ACK后,需要有个TIME-WAIT阶段,等待一段时间后,再真正关闭连接
一般是等待2倍的MSL(Maximum Segment Lifetime,最大分段生存期)

  • MSL是TCP报文在Internet上的最长生存时间
  • 每个具体的TCP实现都必须选择一个确定的MSL值,RFC 1122建议是2分钟
  • 可以防止本次连接中产生的数据包误传到下一次连接中(因为本次连接中的数据包都会在2MSL时间内消失了)

如果client发送ACK后马上释放了,然后又因为网络原因,server没有收到client的ACK,server就会重发FIN这时可能出现的情况是

  • client没有任何响应,服务器那边会干等,甚至多次重发FIN,浪费资源
  • client有个新的应用程序刚好分配了同一个端口号,新的应用程序收到FIN后马上开始执行断开连接的操作,本来它可能是想跟server建立连接的

为什么释放连接的时候,要进行4次挥手?

TCP是全双工模式

  • 第1次挥手:当主机1发出FIN报文段时
    表示主机1告诉主机2,主机1已经没有数据要发送了,但是,此时主机1还是可以接受来自主机2的数据
  • 第2次挥手:当主机2返回ACK报文段时
    表示主机2已经知道主机1没有数据发送了,但是主机2还是可以发送数据到主机1的
  • 第3次挥手:当主机2也发送了FIN报文段时
    表示主机2告诉主机1,主机2已经没有数据要发送了
  • 第4次挥手:当主机1返回ACK报文段时
    表示主机1已经知道主机2没有数据发送了。随后正式断开整个TCP连接

有时候在使用抓包工具的时候,有可能只会看到“3次“挥手,这其实是将第2、3次挥手合并了

image-20220705110046874

当server接收到client的FIN时,如果server后面也没有数据要发送给client了这时,server就可以将第2、3次挥手合并,同时告诉client两件事

  • 已经知道client没有数据要发
  • server已经没有数据要发了

【长连接&短链接】

发完信息不断开是长连接,发完信息断开是短连接

【建立连接后不发数据的影响】

建立连接后会在内存中维护一个socket对象,如果不断开连接且不发送数据,会导致内存资源的浪费。