Files
rikako-note/tcpip/tcp_ip协议.md
2025-01-28 13:58:12 +08:00

390 lines
24 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# tcp/ip详解-协议
## 概述
### 四层协议系统
TCP/IP协议族通常被认作是四层协议系统每层分别负责不同功能由下到上分别为
1. 链路层(数据链路层)
2. 网络层负责分组在网络中的活动例如分组的选路等。网络层协议通常包含ip协议,icmp协议igmp协议
3. 传输层负责在两台主机之间提供端到端的通信tcp/ip协议族中传输层协议有TCP和UDP
4. 应用层:负责处理特定的协议细节
> #### IGMP
> IGMP为internet组管理协议其用于将udp数据报广播到多个主机
> #### ARP & RARP
> ARP和RARP是某些网络接口使用的特殊协议用于转换ip层和链路层所使用的地址。
### ipv4地址
ipv4地址大小为4字节其分类如下所示
- A类 0~127.xxx.xxx.xxx (第一bit为0)
- A类地址组成为`0` + 7bit `net id` + 24bit `host id`
- B类 128~191.xxx.xxx.xxx (前两位bit为10)
- B类地址组成为`10` + 14bit `net id` + 24bit `host id`
- C类: 192~223.xxx.xxx.xxx (前三位bit为110)
- `110` + 21bit `net id` + 8bit `host id`
- D类224~239.xxx.xxx.xxx (前四位bit为1110)
- `1110` + 28bit `multicast group id`
- E类240~255.xxx.xxx.xxx (前五位bit为11110)
- `1111` + 28bit `reserved for future use`
### 协议层封装
当应用向网络中发送数据时,数据被送入协议栈中,从上到下,从应用层一直到数据链路层,每层协议都会为上一层提交的数据添加首部或尾部信息,并且将修改后的数据传递给下一层。
其中,个数据层叫法如下:
- tcp传递给网络层的数据被称为tcp段tcp segment
- 网络层传递给数据链路层的数据被称为ip数据报ip datagram
- 通过以太网传输的数据流被称为帧frame
> #### 以太网数据帧
> 以太网数据帧,其以太网首部长度为`14字节`,尾部为`4`字节。
>
> 且数据帧的长度必须位于46字节~1500字节之间
> #### packet
> 更确切说ip传递给数据链路层的是分组packet分组可能是ip数据报ip datagram也可能是ip数据报的一个片fragment
> #### UDP datagram
> UDP数据和TCP数据类似UDP传递给IP的数据被称为UDP数据报UDP datagram
>
> UDP首部长度为8字节。
> #### IP首部
> 除了TCP, UDP向IP传递数据外`ICMP`和`IGMP`也会向IP传输数据即使ICMP和IGMP和IP都位于网络层。
>
> 故而IP首部中存在长度为8bit的范围用于标识传递给ip的协议。该字段中1表示ICMP2表示IGMP6表示TCP17表示UDP。
> #### TCP/UDP首部中的端口号
> 有很多程序都使用UDP/TCP来传递数据故而需要通过端口号来标识程序。
>
> 端口号长度为16bit范围为`0 ~ 65535`tcp和udp把源端口号和目标端口号存放在报文首部。
> #### 数据链路层标识传递数据的协议
> 类似于ip网络接口不仅会被ip传递数据ARP和RARP即使和网络接口一样位于数据链路层但是仍然会向网络接口传递数据。故而以太网帧的首部同样存在一个16bit的区域用于标识传递数据的协议。
### 分用
当目标主机接收到网络上传输到的数据时,会沿着协议栈至底向上传递。
在每层协议从下层协议接收到数据时,会去掉本层的首部/尾部。每层协议都会检查首部中的标识区域,用于判断上层协议,并将去掉首部/尾部后的数据传递给上层协议。这个过程被称之为`分用`
各层协议其对应上层协议可能为:
- 以太网网络接口:上层协议可能为`ARP, RARP, IP`
- IP协议上层协议可能为`ICMP, IGMP, TCP, UDP`
- TCP, UDP: 上层可能为各种应用层序通过来源ip、来源端口号、目标端口号进行判断
## 数据链路层
TCP/IP中以太网数据报的封装格式在`RFC894`IEEE 802网络的ip数据报则是封装在`RFC 1042`中。
对于Internet主机必须要求
- 必须能接受和发送RFC 894封装格式的分组
- 应该能接受`RFC 894``RFC 1042`封装格式的分组
- 也许能发送`RFC 1042`封装格式的分组
RFC 894是最常被使用的封装格式如下为两种格式的定义。
### RFC 1042
`目的物理地址(6字节)` + `源物理地址(6字节)` + `长度(2字节)` + `802.2 LLC(3字节)` + `802.2 SNAP(5字节)` + `数据(38 ~ 1492字节)` + `CRC(4字节)`
其中,字段含义如下:
- `目的/源地址`:目的/源地址均代表物理地址长度均为6字节48bit
- `长度`: RFC 1042中长度代表`长度`字段后续`不包含CRC`的长度
- `CRC`: CRC字段用于帧内字节差错的循环冗余校验
### RFC 894
`目标物理地址(6字节)` + `源物理地址(6字节)` + `类型(2字节)` + `数据(46 ~ 1500字节)` + `CRC(4字节)`
其中,字段定义如下:
- `类型`:以太网帧中`类型`字段定义了被封装数据的协议类型:
- `0800`: 如果类型字段的值为`0800`那么代表后续数据为IP数据报
- `0806`: 如果类型字段值为`0806`那么代表后续数据为ARP请求/应答
- `0835`: 如果字段类型为`0835`那么代表后续数据为RARP请求/应答
RFC 894和RFC 1042定义的帧必须有最小长度要求RFC894要求数据长度至少为46字节而RFC1042要求数据长度至少为38字节为了保证被封装数据长度达到最小长度要求必须`在长度不足时向剩余空间填充pad字节`
### 环回接口
大多数产品都支持环回接口(loopback interface)允许运行在同一台机器上的程序之间相互进行通信。在A类地址中`127`开头的地址即是为环回端口预留。根据惯例,大多数系统把`127.0.0.1`分配给这个接口并命名为localhost。
> 一个传给loopback interface的ip数据包不能在任何网络上出现。
### MTU
RFC 894和RFC 1042对数据帧长度有限制数据部分长度最多不能超过1500和1492字节该限制被称为最大传输单元MTU
如果ip层需要传输一个大于MTU的数据报那么该数据报需要被分片为若干片令每一片都小于MTU限制的大小。
## ip:网际协议
ip协议为tcp/ip中最为核心的协议TPC/UDP/ICMP/IGMP数据都以ip数据报的形式进行发送。
### IP协议特性
#### 不可靠
ip协议是不可靠的其并不保证传输的数据被成功送达目标端。如果在ip数据包发送途中某个路由器暂时用完缓冲区那么ip协议存在简单的错误处理算法丢弃该ip数据报并且向信源段发送ICMP消息报。
#### 无连接(connectionless)
`无连接`代表ip数据报并不维护任何状态信息每个数据报的处理是相互独立的。故而`ip数据报可以不按发送的顺序进行接收`
> 例如发送端向接收端发送了两个连续的数据报先发送A再发送B每个数据报都会独立的进行路由选择`数据报B可能和数据报A选择不同的路线故而数据报B可能在数据报A之前到达`。
### Ip首部
ip首部的格式如下所示
<img alt="" src="https://i-blog.csdnimg.cn/blog_migrate/4d1fb93f93476f6089e8cff145ea3192.jpeg">
#### 首部各字段含义
##### 版本
版本长度为4bit代表ip协议版本号ipv4场景下该值为4
##### 首部长度
首部长度指首部占32bit字的数目包括`选项`。首部长度占4bit故而ip协议首部最长为`(2^4-1) * (32/8) bytes = 15 * 4 bytes = 60bytes`
对于普通ip数据报没有任何选项其首部长度为20字节故而首部长度的值为`20 / 4 = 5`
##### 服务类型TOS
TOS字段长度为8位其组成如下
- `优先权`子字段3bit现在会被忽略
- `TOS`子字段4bit
- 未用位1bit该位目前没有被使用但是必须置为0
TOS子字段其4bit分别代表如下含义最小时延、最大吞吐量、最高可靠性、最小费用。其4bit中最多只能有一bit被置为1如果4bit均位0则代表是一般服务。
> 目前,`绝大多数tcp/ip实现都不支持TOS特性`.
##### 总长度
总长度指整个ip数据报的长度单位为字节。例如用首部长度和总长度字节就能得知ip数据报中内容起始位置和长度。
总长度字段其长度为16位故而ip数据报最大长度为`65535`字节。但是受数据链路层协议MTU影响当ip数据报被分片时总长度的值也会随着分片而变化。
> 而且由于数据链路层协议拥有传输数据的最小长度限制例如以太网协议其数据最小长度为46字节。而ip数据报其长度可能小于46字节。
>
> 当ip数据报大小小于46字节时以太网协议会对不足46字节的部分进行填充故而总长度字段能够实标识该数据报的实际大小去除被以太网协议填充的字节。
##### 标识
标识字段为16bit其会唯一标识主机发送的每一份数据报通常每发送一份报文其值会加一。
##### 标志字段和位偏移字段
标志字段和位偏移字段和分片操作有关分别为3bit和13bit。
##### TTL
TTL字段设置了数据报可以经过的最多路由器个数其指定了数据报的生存时间。`TTL字段的长度为8bit`
TTL字段的初始值由源主机及逆行设置通常为32或64。每当数据报经过一个路由器的处理那么ttl字段的值就会减1。`当ttl字段的值为1时该数据报将会被丢弃并发送ICMP`报文来通知源主机。
##### 协议
协议字段长度为8 bit可以用于标识IP协议的上层协议。通过协议字段可以实现对ip协议的分用。
##### 首部校验和
首部校验和字段长度为16bit其根据ip首部计算校验和码并不对首部后的数据进行计算。
关于数据的校验和其在上层TCP,UDP,ICMP,IGMP协议协议首部中均含有`同时覆盖首部和数据内容的校验和码`
> 在计算首部校验和时首先将校验和字段设置为0之后对首部中每个16bit字进行二进制反码求和并将结果保存到校验和字段中。
>
> 接收方在接收到数据报后会对首部每个16bit进行二进制反码求和并且要求计算结果全为1。如果校验错误那么ip协议会要求丢弃接收到的数据报但是不生成差错报文由上层协议发现丢失的报文并进行重传。
> 在路由器在针对ip报文进行转发时通常需要将ip数据报的ttl减一故而其需要对ip首部校验和的值进行增加(并不需要重算整个ip首部的校验和).
##### 源ip地址和目标ip地址
每个ip数据报都包含源ip地址和目标ip地址均为4字节32bit。
##### 选项
最后,选项字段是一个可变长度的可选信息。这些选项很少被使用,也并非所有的主机和路由器都支持这些选项。
选项字段通常以32bit作为界限在必要时候会填充0保证ip首部长度始终为32bit4字节的整数倍。
### ip路由选择
通常来说当目标主机和源主机位于同一个子网内时ip数据报可以直接发送到目标主机。但是当目标主机和源主机跨网络通信时源主机则是将ip数据报发送给默认路由器并由路由器来转发该数据报。
IP发送数据报场景如下
- 从上层TCP, UDP, ICMP, IGMP中接收数据报并进行发送
- 从一个网络接口接收数据报并进行发送(转发数据报)
ip层在内存中拥有一个路由表当接收到数据报从上层协议或从网络接口会搜索该路由表
- 如果数据报来源为某个接口时首先检查目标ip地址是否为本机ip地址之一或广播ip地址
- 如果是数据报则被送到ip首部中协议字段所定义的协议模块进行处理
- 如果不是上述地址之一,则处理逻辑如下
- 如果ip层被设置为路由器功能则对数据报进行转发
- 如果ip层未被设置为路由器功能则丢弃该数据报
> 故而未被设置为路由器功能的主机在网络接口接收到ip数据报时首先会判断该ip数据报是否目标地址为本机的ip或广播ip数据报是否是发送给自己的。如果是则传递给上层协议模块如果不是则丢弃该ip数据报
路由表每一条记录都包含如下信息:
- 目标ip地址可以是主机地址也可以是网络地址
- 下一跳路由器的ip地址或是位于直接相连网络中的ip地址
- 标志标识目的ip地址是主机还是网络
- 指定数据报应该被传输给哪个网络接口不同的网络接口连接不同的子网路由表即使将指定ip地址的请求路由到指定的网络接口
ip路由选择是逐跳hop-by-hop进行的。
ip路由选择主要执行如下逻辑
- 搜索ip路由表找到能够和目的ip完全匹配的条目如果能找到发送
- 搜索路由表,找到能与目的网络号匹配的条目,如果找到,发送
- 搜索路由表找到default条目发送
如果上述尝试都失败,那么该数据报将无法被传达,会向生成数据报的应用程序发送`主机不可达``网络不可达`的错误。
### 子网
对于A类或B类地址其分别能容纳`2^24-2``2^16-2`数量的主机同一网络中并不需要这么多主机故而通常会建立子网将host id分割为子网号和主机号示例如下。
#### 组建子网示例
B类地址组建子网示例如下
- 网络号: 16位 `01` + 14bit
- 子网号8位
- 主机号8位
上述示例中将16bit host id中的8位划分给子网8位划分给主机号故而允许有254个子网和254台主机全0或全1地址无效
> 在根据host id划分子网和主机位数时并不要求以字节划分故而16位host id可以划分4bit给子网12bit给主机故而能拥有14个子网每个子网最多拥有16382台主机
### 子网掩码
子网掩码用于标识host id中有多少bit用于子网号有多少bit用于主机号。和ip地址类似子网掩码也是32bit大小含义如下
- 分配给net id和子网号的bit值为1
- 分配给主机号的bit值为0
示例如下:
假设一个B类地址`172.19.23.153`,其子网掩码为`255,255.255.0`代表16bit的host id中有8位被分配给子网8位被分配给主机。
### endianness
endianness代表字节在内存中的排列顺序在不同计算机操作系统中endianness可能有所不同。故而在不同主机通过网络进行数据交换时必须通过相同的endianness进行数据的发送和接收。
endianness通过存在两种格式`big endian``little endian`:
- big endian首先存储MSB即MSB位于内存地址较低的字节
- little endian首先存储LSB即LSB位于内存地址较低的字节
#### big endian
在big endian system中 `most significant byte`MSB存储在内存的低位地址上。例如对于32 bit的integer `0x12345678`其在big endian system中的存储顺序如下
```
Address: 00 01 02 03
Data: 12 34 56 78
```
其中,`0x12`为MSB存储在内存最低位地址`00`上,而`0x78`则是存储在最高位地址`03`上。
#### little endian
在little-endian system中`least significant byte`LSB存储在内存的较低位地址上。例如对于32 bit的integer`0x12345678`其在little endian system中存储顺序如下
```
Address: 00 01 02 03
Data: 78 56 34 12
```
其中,`0x12`位MSB其存储在最高位地址上`03`
#### MSB & LSB
MSB & LSB的概念可以参照如下十进制示例。
> 对于10进制数`2984`,将其个位修改为`5`会导致整体数值加1而将千位`2`改为`3`则将导致整体数值增加`1000`,故而,可看作千位相较于个位`more significant`。
MSB和LSB的定义如下
- MSB: The byte that holds the highest position value
- LSB: The byte that holds the lowest position value
#### 网络字节传输顺序
网络字节传输中,通常都按照`big endian`字节序来进行传输。
操作系统中,`unbuntu``windows`都采用`little endian`
## tcp
### tcp服务
尽管tcp和udp都同样使用ip层但是tcp却提供和udp完全不同的服务。tcp提供了一种面向连接的、可靠的字节流服务。
#### 面向连接
面向连接代表两个tcp应用在通信时必须要先建立一个tcp连接。在一个tcp连接中仅有两方进行通信广播和多播无法应用于tcp连接。
#### 可靠性
tcp通过如下方式来提供可靠性
- 数据应该被分割成tcp认为最适合发送的数据块由tcp传递给ip的信息单位被称为报文段或段segment
- 当tcp发出一个segment后其将启动一个定时器并等待目的端收到该报文的确认。如果在指定时间内未接收到目的端的确认ack将针对该报文段进行重传
- 当tcp收到来源于tcp另一端的数据其将回复一个确认该确认并非立即发送而是通常会等待一段时间几分之一秒
- tcp将会维护其首部与数据的校验和其是一个端到端的校验和目的是检测数据在传输过程中是否发生变化。
- 如果校验和不符那么tcp将会丢弃接收到的报文段并且不针对该报文段作确认超时重传
- tcp数据段会通过ip数据报来进行传输而ip数据报并不会保证到达的顺序故而tcp数据段也可能会乱序到达
- tcp会针对接收到的数据段集合重新进行排序确保接收到的数据能被成功交付给应用层
- 因为ip数据报可能会发生重复故而tcp需要对重复数据进行丢弃
- tcp还能提供流量控制tcp的每一方都有大小固定的缓冲空间tcp接收方`只允许tcp发送方发送接收方缓冲区所能容纳的数据`
- 这将避免发送方发送过快导致接收方缓冲区溢出,用于协调发送方发送速率
#### 字节流服务
两个应用之间可以通过tcp连接交换8bit字节构成的字节流。`tcp不在字节流中插入任何记录标识符`
故而当发送方先发送10字节再发送20字节最后发送50字节时`tcp的接收方无法获知tcp发送方发送了几次以及每次发送多少字节`
> 在发送方分3次发送了80字节的场景下接收方接收数据的次数以及每次接收的字节数并不一定和发送方相同。
>
> 例如发送方分三次每次发送102050字节的数据但接收方可能分四次每次接收20字节来接收发送方发送的数据。
>
> tcp并不保证发送方的发送数据次数以及每次发送数据大小与接收方完全相同tcp可靠性只保证发送方分多次发送的数据都能被接收方正确接收到对于接收次数和每次接收字节大小没有限制。
此外tcp对于字节流内容并不做任何解释tcp不知道传输的数据是二进制数据或文本数据对于数据内容的解释由tcp连接双方的应用层来进行。
### tcp首部
tcp数据被封装在一个ip数据报中其格式如下
```
ip首部 + tcp首部 + tcp数据
20字节 20字节
```
tcp首部的数据格式如下如果不考虑选项字段那么tcp首部的大小为20字节
<img src="https://i-blog.csdnimg.cn/blog_migrate/9f452960afed4f2cccdcebad37785d39.png" alt="">
tcp首部各字段含义如下
#### 源端口号,目的端口号
源端口号和目标端口号长度均为16位范围为`0~65535`
源端口号和目的端口号用于查找发送方和接收方的应用程序进程,`源端口号 + 目的端口号 + 源ip地址 + 目的ip地址`这个四元组能够唯一确定一个tcp连接。
一个ip地址和一个端口号也被成为一个socketsocket pair源ip+源端口号+目标ip+目标端口号则也是可以唯一确定一个tcp连接双方。
#### 序列号
序列号长度为32bit用于标识tcp发送端向tcp接收端发送的数据字节流其表示在当前报文段中的第一个数据字节。
> 如果将字节流是两个应用程序间的单向流动则tcp则通过序列号对每个字节进行计数。序号是无符号的32bit整数并且会在达到最大值2^32-1后重新从0开始计数。
##### tcp连接建立
当创建一个新的tcp连接时控制位中的`SYN`标志位为1序列号字段则包含主机选择的初始序号ISN(initial sequence number)。
建立连接后主机发送数据的第一个字节其序列号为ISN因为标志会消耗一个序号。
#### 确认序列号
确认序列号长度为32bit。
每个传输的字节都会被计数序列序列号的值则是ack的发送方希望接收到的下一个序列号`即确认序列号应该为已经接收到的数据字节序列号+1`
发送无需任何代价的确认序列号和标志位都被包含在tcp首部中故而当连接建立后发送的报文段中总是包含确认序列号字段标志位也总是为
##### 全双工
tcp为应用层提供了全双工的服务,其意味着数据能够在两个方向上独立的进行传输,连接的双方必须维护两个方向上的传输序列号。
##### 选择性确认
tcp协议并不能进行选择性确认。tcp中的ack只能针对`位于xxx位置之前的数据已经全部被接收`这种场景进行确认,但是对如下场景,tcp协议并不支持:
- `1-1024`字节已经被接收,并且接收到另一个报文段`2049~3072`,此时接收方无法针对新的报文`2049~3072`进行ack,因为`1025~2048`尚未被接收,故而接收方只能发送确认序列号为1025的ack
- tcp也无法执行nack操作,例如,`1025`报文段被接收,但是校验和校验失败,那么接收方也只能发送确认序列号为1025的ack,无法对校验失败的报文段执行nack操作。
#### 首部长度
首部长度字段代表tcp首部32bit字的长度,即单位为4字节。首部长度字段占4bit,即代表tcp首部长度最多只能为60字节。
当没有选项时,正常tcp首部长度为20字节。
#### 标志位
tcp首部中存在6个标志位其中多个标志位可以同时被设置为1标志位的简介如下。
- URG: 紧急指针有效
- ACK: 确认序列号有效
- PSH: 接收方应该尽快将该报文段交给应用层
- RST: 重新建立连接
- SYN: 同步序列号,用于发起一个连接
- FIN: 发送端完成发送任务
#### 窗口大小
窗口大小用于进行tcp的流量控制窗口大小字段的长度为16bit故而窗口大小最大为65535字节。
tcp由每一端通过声明窗口的大小来提供流量控制。窗口大小为字节数开始位置为确认序列号字段指明的值。
#### 校验和
校验和字段为16bit覆盖了整个tcp报文段包含tcp首部和tcp数据。
校验和字段由发送方进行计算和存储,并且由接收方进行校验。
#### 紧急指针
紧急指针长度为16bit仅当URG标志位置位时才有效。紧急指针代表一个正的偏移量和序列号字段相加后的值表示紧急数据最后一个字节的序列号。
tcp的紧急方式是发送方向另一方发送紧急数据的方式。
#### 可选字段
最常见的可选字段为最长报文大小MMS, Max Segement Size每个连接方通常都在通信的第一个报文段SYN置位的那个报文段中指明了MMS选项。
#### 数据部分
在tcp报文段中数据部分是可选的如果一方没有数据需要发送那么tcp报文段中并不包含数据部分只包含tcp的首部。