TCP/IP五层协议栈(1)

时间:2022-12-10 15:55:15

1.应用层协议

应用层协议相对来说比较简单,因为其他层的协议属于硬件上的.相对程序员来说已经固定了.不需要自己设计和实现了.

设计应用层协议有两个要点

  • 要约定好传输的数据
  • 还要约定好数据的格式

1.1.协议模板

虽说可以自己设计,不过当前已经有很多模板被大佬设计好了.这里我们介绍几个常见的模板

1.1.1.xml

xml是由标签构成的.主要样式为: <标签名>内容</标签名> .标签名是可以嵌套的.

(样式如下图)
TCP/IP五层协议栈(1)

虽然xml格式的可读性很高,但是引入了很多的辅助信息.是比较浪费带宽的.而在网络传输中,宽带开销是比较高的.因此xml现在很少作为应用层协议的设计模板.现在使用xml主要是作为一些配置文件.

1.1.2.JSON

JSON数据格式主要是一个 {} 中包含很多键值对.键值对之间用逗号分割,键和值之间用冒号分割.键是字符串类型,值未限制类型.

JSON 中单引号和双引号都表示字符串,由于 JSONkey 必须是字符串.所以一般情况下key的引号是可以省略的.

(样式如下图)

TCP/IP五层协议栈(1)

虽然 JSON 在当前是比较流行的数据格式. 但是 JSON 在表示一个复杂的数组时,key会出现多次,数据还是会产生冗余.

1.1.3.protobuffer

protobuffer是一种二进制格式的数据

在protobuffer的数据中,不再包含上面key 的名字了.而是通过顺序以及一些特殊符号,来区分每个字段的含义. 同时再通过一个IDL文件来描述这个数据格式(描述各个部分都是什么意思)

IDL 只是起到一个辅助开发的效果,并不会真正的进行传输.传输的只是二进制的纯粹的数据.

2.传输层协议

常见的传输层协议有两种 TCPUDP .

2.1.UDP数据格式

UDP报头 (源端口+目的端口+报文长度+校验和.大小均为2字节,UDP报头总大小为8字节) + UDP数据载荷 (完整的应用层数据)

(UDP数据格式如下图)
TCP/IP五层协议栈(1)

应用层数据报封装成UDP数据报,本质上就是在应用层数据报的基础上添加了8个字节的报头.

  • 报文长度:2字节(范围:0-65535(单位字节)->最大就是64k)
    • 如果需要传送较大的数据,主要做法就是在应用层对数据报进行分包,然后再发送.接收方再把收到的数据报重新拼接成一个完整的数据
  • 校验和:用来验证数据是否正确(准确率不是100%(校验和正确,数据不一定真的正确.但是检验和错误的时候,数据一定有问题)).

2.2.TCP数据格式

TCP报头 (16位源端口+16位目的端口+32位序号+32位确认序号+4位首部+6位保留位+(6个标志位)+16位窗口大小+16位校验和+16位紧急指针+选项) + 应用层数据

六个标志位 : URG ACK PSH RST SYN FIN ,标志位已经有固定含义,所以传输时,只需要将标志位置为0/1. 1就表示选择了当前含义.(例如:ACK标志位为1时,表示当前报文是确认报文段)

  • URG: 紧急报文段
  • ACK: 确认报文段
  • PSH: 推送报文段
  • RST: 复位报文段
  • SYN: 同步报文段
  • FIN: 结束报文段

(TCP数据格式如下图)
TCP/IP五层协议栈(1)

TCP选项是不确定的,所以TCP数据报的大小也不固定.

2.3.TCP传输机制

2.3.1.确认应答(保证可靠传输的核心机制)

  • 接收方收到消息之后,给发送方返回一个应答报文(ACK,acknowledge),表示自己已经收到了.
  • 由于网络环境不确定,就会产生一种情况:后发先至(多个以太网数据帧之间)
    • 后发先至的解决方法:
    • 对消息进行编号(序号 和 确认序号).
    • 确认序号 表示当前这个应答报文是针对哪个消息进行的确认应答.
  • TCP并不是根据消息条数进行编号.而是根据字节, 每个字节都进行了编号.
    • 发送的数据中序号就是发送的字节数据范围.
    • 确认应答报文中的确认序号就是当前从头接收到了哪个字节(从头拼接到数据断开的字节序号)

2.3.2.超时重传(对确认应答的补充)

  • 如果传输中丢包,就会缺少要等待的ACK(确认报文).传输方等待一定时间后还没有收到ACK.就重新发送一次数据.
  • 正常网络情况下,连续丢包两次的概率是比较低的.所以如果连续重传失败,就会放弃重传.断开TCP连接.
  • 但是丢包是分情况的
    • 如果是发送的数据丢了,重新发送对整体不会有影响.
    • 如果是应答报文ACK丢了.就会重复发送两次数据,如果没有处理就会比较危险.(TCP内部会进行去重操作)

2.3.3.连接管理

2.3.3.1.如何建立连接(三次握手)

三次握手:客户端和服务器之间,通过三次交互建立连接.(客户端发起请求)

(三次握手过程如图)
TCP/IP五层协议栈(1)

  • 三次握手之所以是三次是因为服务器返回时将(ACK和SYN)打包在一个报文中发送(让两个标志位同时为1)
    • 也可以不将(ACK和SYN)打包在一起发送(四次握手)
  • 因为三次握手中间的 ACK+SYN 都是操作系统负责进行的.中间不会有很长的间隔,所以是可以打包的.
  • 三次握手的作用:
    • 检查当前这个网络的情况是否满足可靠传输的基本条件.(主要)
    • 三次握手的同时也会相互交互一些信息.
  • 三次握手交互的信息在建立连接之后会被客户端和服务器双方保存.
    • 主要信息就是五元组.源IP,源端口,目的IP,目的端口,协议类型(TCP)

2.3.3.2.如何断开连接(四次挥手)

四次挥手:客户端和服务器之间,通过四次交互断开连接.(发送方可能是客户端,也可能是服务器)

(四次挥手过程如图)
TCP/IP五层协议栈(1)

  • 中间发送ACK和FIN不合并的原因:两个报文发送的时机是不同的.
    • 四次挥手中间的 ACK 是内核负责的.而 FIN 是用户代码负责的(调用close触发).因此一般这两个报文是不可以合并的.所以一般不可以是三次挥手.
    • 但是,当在第一次挥手之后,如果被动方没有数据要发给主动方.第二和第三次挥手就有可能合并传输. 这样就出现了三次挥手.
  • 第四次挥手的ACK发送结束后,发送端资源不会立即销毁,会有一个超时时间(TIME_WAIT),时间长度为 2MSL
    • 预防最后一次传输过程中ACK丢包(等待接受重传的FIN:因为如果ACK丢包,接收方就会重新发送一次FIN.当再次接受到FIN,就说明ACK丢包.需要重新发送)