2017-8-31
\[N_EMQX\]
\[Java Email\]
OSI 7层模型
OSI 是 Open System Interconnect的缩写,意为开放式系统互联. 是国际标准化组织(ISO)提出的一个概念性框架,用于定义网络通信系统的标准架构.
OSI七层参考模型的各个层次的划分遵循下列原则:
1、同一层中的各网络节点都有相同的层次结构,具有同样的功能.
2、同一节点内相邻层之间通过接口(可以是逻辑接口)进行通信.
3、七层结构中的每一层使用下一层提供的服务,并且向其上层提供服务.
4、不同节点的同等层按照协议实现对等层之间的通信.
把网络通信的工作分为7层,从下到上分别是 物理层,数据链路层,网络层,传输层,会话层,表示层和应用层;
盗图 from : https://blog.csdn.net/qq_39521554/article/details/79894501
物理层(PhysicalLayer)
规定通信设备的机械的、电气电压、功能的和过程的特性,具体地讲,机械 特性规定了网络连接时所需接插件的规格尺寸、引脚数量和排列情况等;
属于物理层定义的典型规范代表包括: EIA/TIA RS-232、EIA/TIA RS-449、V.35、RJ-45等.
代表设备: 集线器,中继器
in short 看的见的东西: 网线,引脚; 看不见的东西: 引脚的定义,电气电压
关于 T568B 的引脚定义
也就是网线网口..
| 引脚 |
线色 (T568B) |
功能 (1000BASE-T) |
功能 (100BASE-TX) |
功能 (10BASE-T) |
| 1 |
白橙 |
发送数据+ (Tx_D1+) |
发送数据+ (Tx+) |
发送数据+ (Tx+) |
| 2 |
橙 |
发送数据- (Tx_D1-) |
发送数据- (Tx-) |
发送数据- (Tx-) |
| 3 |
白绿 |
接收数据+ (Rx_D2+) |
接收数据+ (Rx+) |
接收数据+ (Rx+) |
| 4 |
蓝 |
双向数据3+ (Bi_D3+) |
未使用 |
未使用 |
| 5 |
白蓝 |
双向数据3- (Bi_D3-) |
未使用 |
未使用 |
| 6 |
绿 |
接收数据- (Rx_D2-) |
接收数据- (Rx-) |
接收数据- (Rx-) |
| 7 |
白棕 |
双向数据4+ (Bi_D4+) |
未使用 |
未使用 |
| 8 |
棕 |
双向数据4- (Bi_D4-) |
未使用 |
未使用 |
|
|
|
|
|
- 10M/100M网络(百兆及以下) : 实际上只使用了1,2,3,6这四根线(两对线). 1、2用于发送数据,3、6用于接收数据. 4、5、7、8是空闲的.
- 1000M网络(千兆网络) : 使用全部8根线(四对). 每一对线都可以进行双向数据传输.
数据链路层
介于物理层 和网络层 之间。它在物理层提供的原始比特流传输服务的基础上,为网络层提供可靠、无差错的数据传输服务,其核心任务是在相邻节点之间建立、维护和释放数据链路连接
成帧 数据链路层最基础的工作。它将来自网络层的比特流(原始的0、1序列)封装成具有特定结构的"帧",而不是以比特流为单位进行传输。每个帧包含帧头 、数据部分(有效载荷) 和帧尾。帧头通常包含目的和源地址(MAC地址)等控制信息,帧尾则包含用于差错检验的序列(如循环冗余校验CRC)
代表设备: 交换机
in short 它主要的工作是封装为数据帧,提供差错校验等,考虑的是两个相邻节点之间可靠的传输数据帧
此时数据中包含帧的概念了
网络层
在计算机网络中进行通信的两个计算机之间可能会经过很多个数据链路,也可能还要经过很多通信子网. 网络层的任务就是选择合适的网间路由和交换结点,确保数据及时传送.
代表协议主要包括: IP,IMCP,IGMP,ARP RARP
代表设备: 路由器
in short 它主要主要的工作是 路径选择与路由,逻辑寻址(局域网使用MAC地址,跨网络通信使用IP地址) 考虑在不同网络网络之间通信
此时封包中包含IP
传输层
第一个实现端到端(即应用程序进程到应用程序进程)通信的层次。它的根本目的是为运行在不同主机上的应用进程提供逻辑通信,让应用开发者无需关心底层网络(如路由器、交换机)的具体细节
代表协议主要包括: TCP,UDP
in short 它主要主要考虑的是 运行在不同主机上的应用程序进程之间如何可靠地通信
此时封包中包含端口号
会话层
in short 它主要主要考虑的是 应用程序之间通信过程的逻辑状态。它管理的是这次"对话"如何开始、如何进行、如何暂停和恢复,以及如何结束
此时大部分程序自己的数据逻辑定义; 纯逻辑定义 比如用户登录,退出
表示层
in short 它不关心数据如何传输,而是专注于数据的" 表示形式**",确保发送方应用程序生成的数据,能被接收方应用程序正确理解和使用**
也是纯逻辑定义,例如: 数据传输的 序列化与反序列化的结构
应用层
为操作系统或网络应用程序提供访问网络服务的接口,用户接触的多为这一层, 例如想传输文件使用FTP协议,收发邮件使用POP3/IMAP(收)、SMTP协议,想使用web服务使用 HTTP 协议。
由此可见,从会话层到应用层, 相当于要网络定义中,规范程序的开发? 这分为三层纯属冗余
TCP/IP 模型
OSI 只是存在于概念和理论上的一种模型,它的缺点是分层太多,增加了网络工作的复杂性; 后来人们对 OSI 进行了简化,合并了一些层,最终只保留了4层,从下到上分别是接口层 ,网络层 ,传输层 和应用层 ,这就是大名鼎鼎的TCP/IP 模型;
TCP协议
TCP 的数据包结构
| 字段名称 |
长度(比特) |
长度(字节) |
描述 |
| 源端口 |
16 |
2 |
发送方的应用程序端口号. |
| 目的端口 |
16 |
2 |
接收方的应用程序端口号. |
| 序列号 |
32 |
4 |
用于标识从 TCP 源端向目的端发送的数据字节流. 它表示这个报文段中的第一个数据字节的序号. |
| 确认号 |
32 |
4 |
只有 ACK 标志为 1 时才有效. 表示接收方期望收到的下一个字节的序列号,同时也表明该序号之前的所有数据已正确接收. |
| 数据偏移 |
4 |
0.5 |
指示 TCP 头部长度(以 32 位字为单位). 因为头部长度可变(由于选项字段),所以需要此字段. 最小值为 5(表示 20 字节),最大值为 15(表示 60 字节). |
| 保留 |
6 |
0.75 |
保留给未来使用,必须设置为 0. |
| 控制标志 |
6 |
0.75 |
包含 6 个 1 比特的标志位,用于控制连接状态: - URG : 紧急指针有效. - ACK : 确认号有效. - PSH : 推送功能,请求接收方尽快将数据交付给应用层. - RST : 重置连接. - SYN : 同步序列号,用于建立连接. - FIN: 发送方结束发送,用于关闭连接. |
| 窗口大小 |
16 |
2 |
表示从确认号开始,接收方愿意接收的字节数量. 用于流量控制. |
| 校验和 |
16 |
2 |
用于检查 TCP 头部、数据和伪头部(包含 IP 源、目的地址等)在传输过程中是否出错. |
| 紧急指针 |
16 |
2 |
只有当 URG 标志置 1 时有效. 指出本报文段中紧急数据的末尾在数据流中的位置(相对于序列号的偏移量). |
| 选项 |
可变(0-320比特) |
可变(0-40字节) |
可选字段,长度必须是 32 位的整数倍,不足部分用填充字节补齐. 常见的选项有: 最大段大小(MSS)、窗口缩放因子、时间戳等. |
| 填充 |
可变 |
可变 |
为了确保 TCP 头部长度是 32 位(4 字节)的整数倍而填充的 0. |
| 数据 |
可变 |
可变 |
上层协议(如 HTTP、FTP 等)传递下来的实际数据. 如果连接建立或关闭的报文,此部分可能为空. |
|
|
|
|
WireShark 抓包小用
复制代码
Internet Protocol Version 4,Src: 192.168.3.52,Dst: 120.76.40.233
Data: 00670002ef000ce78e84e5a5b3e5ba97e5ad900024376237...
注意 在win: WireShark 依赖于 winpcap,以后的版本内嵌winpcap会自动询问是否安装
过滤规则(捕获过滤)
参考官方文档\] ()
`[not] primitive [and|or [not] primitive ...]`
tcp port 23 and not src host 10.0.0.5
A capture filter for telnet that captures traffic to and from a particular host
tcp port 23 and host 10.0.0.5
* `host 172.96.255.16` 限定主机
* `port 80` 限定端口
* `host 192.168.5.231 and not port 80` and
### 封包分析
*** ** * ** ***
实例; 访问服务器的第一个报文
```cpp
b05b67e2defc086266326f8b//(链路层12字节)
0800
450000342704400040060000c0a80334276c8248(Internet Protocol Version)//(IP头 20字节)
e13700503eac762400000000800220006db70000020405b40103030201010402(Transmission Control Protocol)//(TCP头 32字节)
```
#### 链路层数据
```cpp
b05b67e2defc//目的mac地址(上一个.路由器的) [6 字节]
086266326f8b//源mac地址(本机网卡接口) [6 字节]
0800//这个意思不太清楚,似乎是固定的; Type: IPv4(0x0800)?
```
#### IP 头
```cpp
45//版本+首部长度[1个字节]
[4] //版本: 占4位(bit),指IP协议的版本号; 目前的主要版本为IPV4,即第4版本号;
[5] //首部长度: 占4位(bit),指IP报文头的长度; 最大的长度(即4个bit都为1时)为15个长度单位,每个长度单位为4字节(TCP/IP标准,DoubleWord),所以IP协议报文头的最大长度为60个字节,最短为20个字节;
00//服务类型: 占8位(bit),[1个字节],
//用来获得更好的服务; 其中的前3位表示报文的优先级,
//后面的几位分别表示要求更低时延,更高的吞吐量,更高的可靠性,更低的路由代价等;
//对应位为1即有相应要求,为0则不要求;
00 34//总长度: 16位(bit),[2个字节]
//指报文的总长度; 注意这里的单位为字节,而不是4字节,所以一个IP报文的的最大长度为65535个字节
27 04//标识(identification): 16位(bit),[2个字节]
//该字段标记当前分片为第几个分片,在数据报重组时很有用;
40 00//标志(flag): 3位(bit)+片偏移: 13位(bit),[共2个字节]
//字段用于标记该报文是否为分片(有一些可能不需要分片,或不希望分片),后面是否还有分片(是否是最后一个分片);
//片偏移: 13位(bit)指当前分片在原数据报(分片前的数据报)中相对于用户数据字段的偏移量,即在原数据报中的相对位置;
40//生存时间: 8位(bit),[1个字节]
//TTL(Time to Live); 该字段表明当前报文还能生存多久;
//每经过1ms或者一个网关,TTL的值自动减1,当生存时间为0时,报文将被认为目的主机不可到达而丢弃;
//使用过Ping命令的用户应该有印象,在windows中输入ping命令,在返回的结果中即有TTL的数值;
06//协议: 8位(bit),[1个字节]
//该字段指出在上层(网络7层结构或TCP/IP的传输层)使用的协议,可能的协议有UDP,TCP,ICMP,IGMP,IGP等;
00 00//首部校验和: 16位(bit),[2个字节]
//用于检验IP报文头部在传播的过程中是否出错,主要校验报文头中是否有某一个或几个bit被污染或修改了;
c0 a8 03 34//源IP地址: 192.168.3.52 32位(bit),[4个字节]
//每一个字节为0~255之间的整数,及我们日常见到的IP地址格式;
27 6c 82 48//目的IP地址: 39.108.130.72 32位(bit),[4个字节]
//每一个字节为0~255之间的整数,及我们日常见到的IP地址格式;
```
#### TCP 头
```cpp
e1 37//源端口号: 16位bit,[2个字节]
//16位的源端口其中包含初始化通信的端口; 源端口和源IP地址的作用是标示报问的返回地址;
00 50//目的端口号: 16位bit,[2个字节]
//16位的目的端口域定义传输的目的; 这个端口指明报文接收计算机上的应用程序地址接口;
3e ac 76 24//序号: 32位bit,[4个字节]
//32位的序列号由接收端计算机使用,重新分段的报文成最初形式;
//当SYN出现,序列码实际上是初始序列码(ISN),而第一个数据字节是ISN+1;
//这个序列号(序列码)是可以补偿传输中的不一致;
00 00 00 00//确认序号: 32位bit,[4个字节]
//32位的序列号由接收端计算机使用,重组分段的报文成最初形式;
//如果设置了ACK控制位,这个值表示一个准备接收的包的序列码;
80 02//首部长度+保留位+6个标志位=16位[共2个字节]
[8]//首部长度: 4位bit,4位包括TCP头大小,指示何处数据开始;
[0 02]//6位标志域; 表示为: 紧急标志,有意义的应答标志,推,重置连接标志,同步序列号标志,完成发送数据标志;
//按照顺序排列是: URG,ACK,PSH,RST,SYN,FIN;
20 00//窗口大小: 16位bit,[2个字节]
//用来表示想收到的每个TCP数据段的大小;
6d b7//校验和: 16位bit,[2个字节]
//16位TCP头; 源机器基于数据内容计算一个数值,收信息机要与源机器数值 结果完全一样,从而证明数据的有效性;
00 00//紧急指针: 16位bit,[2个字节]
//指向后面是优先数据的字节,在URG标志设置了时才有效; 如果URG标志没有被设置,紧急域作为填充; 加快处理标示为紧急的数据段;
020405b40103030201010402//@see可选项参数分析
//这部分可参考: http: //blog.csdn.net/u011414200/article/details/47948401
```
#### Flags 标志值
```cpp
//很重要,根据Flags里的标志值,即上: {80 02 首部长度+保留位+6个标志位=16位[共2个字节]}
//(URG,ACK,PSH. RST,SYN,FIN)判断不同的TCP数据包的类型
SYN 表示建立连接,
FIN 表示关闭连接,
ACK 表示响应,
PSH 表示有 DATA数据传输,
RST 表示连接重置; //RST标识复位,用来异常的关闭链接; 在TCP的设计中它是不可或缺的,发送RST包关闭链接时,不必等缓冲区的数据都发送出去; 直接丢弃缓冲区中的数据,发送RST包; 而接受段收到RST包后,也不必发送ACK包来确认;
其中,ACK是可能与SYN,FIN等同时使用的,比如SYN和ACK可能同时为1,它表示的就是建立连接之后的响应,
如果只是单个的一个SYN,它表示的只是建立连接;
但SYN与FIN是不会同时为1的,因为前者表示的是建立连接,而后者表示的是断开连接;
详细说明.
//Reserved: Not set ------ 保留字段------占 6 位,保留为今后使用
//Nonce: Not set 设置为0 ------ 随机数(Nonce)是任意的或非重复的值,它包括在经过一个协议的数据交换中,通常为保证活跃度以及避免受重复攻击
//Congestion Window Reduced (CWR): Not set ------ 没啥用 =.=
//Urgent: Not set ------ (基本此处无设置) 当 URG=1 时,表明紧急指针字段有效; 它告诉系统此报文段中有紧急数据,应尽快传送(相当于高优先级的数据)
//Push: Set 1 ------(通知接收端立即将数据提交上层,释放内存) 接收 TCP 收到 PSH=1 的报文段,就尽快地交付接收应用进程,而不再等到整个缓存都填满了后再向上交付
//Reset: Not set ------请求重新建立TCP连接,当 RST=1 时,表明 TCP 连接中出现严重差错(如由于主机崩溃或其他原因),必须释放连接,然后再重新建立运输连接
//Syn: Not set ------同步 SYN = 1 表示这是一个连接请求或连接接受报文
//Fin: Not set ------ 请求断开连接,用来释放一个连接; FIN 1 表明此报文段的发送端的数据已发送完毕,并要求释放运输连接;
```
*** ** * ** ***
## TCP 的三次握手
1. 第一次握手: 主机A发送位码为 SYN=1,随机产生seq=1234567的数据包到服务器,主机B由`SYN=1`知道,A要求建立联机;
2. 第二次握手: 主机B收到请求后要确认联机信息,向A发送 ack number=1234568(主机A的seq+1),syn=1,ack=1,随机产生seq=7654321 的包;
3. 第三次握手: 主机A收到后检查ack number是否正确,即第一次发送的seq number+1,以及位码ack是否为1,若正确,主机A会再发送ack number=(主机B的seq+1),ack=1,主机B收到后确认seq值与ack=1则连接建立成功;
至此: 完成三次握手,主机A与主机B开始传送数据;
### TCP数据交互
#### ACK 不断偏移确认数据的过程
dest \> source: seq=421 ack=306 win=xx len=215
目标目前确认接受到306字节(ack),
目标发送数据偏移421(seq) 长度215(len)
source \> dest: seq=306 ack=636 win=xx len=0
源目前确认接受到636字节(ack) *即 421 + 215*
源发送数据偏移306(seq) 长度0(len)
#### 为什么 SYN/FIN 需要消耗序列号?
因为它需要双方对等确认,否则会导致消息重传
#### TCP 窗口更新 Window update
如果一个TCP Window 变为0了,或者接近0了,这就会警告数据发送方没有更多空间来接受更多数据了,数据传输会停止,直到收到一个 update 说 buffer 已经清空了.
## TCP 的四次挥手
1. 客户端A发送一个FIN,用来关闭客户A到服务器B的数据传送(报文段4);
2. 服务器B收到这个FIN,它发回一个ACK,确认序号为收到的序号加1(报文段5); 和SYN一样,一个FIN将占用一个序号;
3. 服务器B关闭与客户端A的连接,发送一个FIN给客户端A(报文段6);
4. 客户端A发回ACK报文确认,并将确认序号设置为收到序号加1(报文段7);
### 为什么需要4次?
* 主机A发送关闭请求 `FIN`,(仅表示我没有数据发送,但此时还可以接受数据的)
* 主机B收到后,发送确认 `ACK` 收到了关闭请求(让主机A知道,收到了关闭请求)
* 主机B传输完数据后了,发送 `FIN` 给主机A (主机A确定了,主机B数据发送完了)
* 主机A收到后,发送确认`ACK` 并等待 2MSL 后关闭连接
#### 第四步的等待
A无法知道`ACK`是否已经到达B,于是开始等待? 等待什么?
1. 假如`ACK`没有到达B,B会为`FIN`这个消息超时重传
2. 那如果A等待时间足够,又收到`FIN`消息,说明`ACK`没有到达B
3. 于是再发送`ACK`,直到在足够的时间内没有收到`FIN`,说明`ACK`成功到达; 关闭连接
为什么是 2MSL?
MSL,Maximum Segment Lifetime,最大报文段生存时间. 即任何TCP报文在网络中存在的最大时长,如果超过这个时间,这个TCP报文就会被丢弃. 2MSL,即两个最大报文段生存时间.
RFC 793 中规定MSL为2分钟,实际应用中常用的是30秒,TCP的TIME_WAIT状态也称为 2MSL等待状态.
# UDP协议
## UDP 广播/多播
UDP广播 它允许一台主机向同一子网内的所有设备发送数据包,非常适合局域网内的群体通信.
| 特性 | UDP广播 | UDP组播 (多播) |
|-----------|------------------------------------------|-----------------------------------------|
| **通信模式** | 一对所有 | 一对一组(特定群体) |
| **目标地址** | 广播地址(如`255.255.255.255`或`192.168.1.255`) | D类组播地址(`224.0.0.0`\~ `239.255.255.255`) |
| **网络影响** | 数据包发送到整个局域网,**通常不被路由器转发**,仅限于本地网络 | 数据包只发送给加入特定组播组的主机,可被路由器转发,适用于广域网 |
## 为什么udp数据包(MTU)不能大于1472字节报文?
以太网(Ethernet)数据帧的长度必须在46-1500字节之间,这是由以太网的物理特性决定的.这个1500字节被称为链路层的MTU(最大传输单元).
因为IP数据报的首部为20字节,所以IP数据报的数据区长度最大为1480字节.
而这个1480字节就是用来放TCP传来的TCP报文段或UDP传来的UDP数据报的.
又因为UDP数据报的首部8字节,所以UDP数据报的数据区最大长度为1472字节.
这个1472字节就是我们可以使用的字节数.
当我们发送的UDP数据大于1472的时候会怎样呢?
这也就是说IP数据报大于1500字节,大于MTU.这个时候发送方IP层就需要分片(fragmentation). 把数据报分成若干片,使每一片都小于MTU.而接收方IP层则需要进行数据报的重组.
这样就会多做许多事情,而更严重的是,由于UDP的特性,当某一片数据传送中丢失时,接收方便,无法重组的数据报,将导致丢弃整个UDP数据报.
[参考: UDP包的大小与MTU](https://blog.csdn.net/wl_fln/article/details/6386365)
# 最后,了解一下数据的标准单位
KB和MB是由 国际单位制(SI)制定的十进制标准,而KiB和Mib是由国际电工委员会(IEC)制定的二进制标准. 也就是通常所说的SI和IEC标准。
> 计算机工业中,在底层的硬件电路中,通用的是二进制,基于十进制的国际单位制对它没用,反而会带来麻烦. 为了方便描述以2为底的大数字幂,工程师们联合了起来,由国际电工委员会(IEC)制定了新的用于1024进位的数字前缀,其实就是将原本对应单词中的最后两位改成了"bi",以代表二进制(binary),而对应的缩写,也从原本的单字母变成了附上"i",比如kB变成KiB,MB变成MiB,全称为kibibytes,mebibytes.
> 但因为这套标准在1998年才提出,虽然马上写入了ISO标准中,但当时Windows都已经出Windows 98了,所以并没能很好的统一整个计算机业界,很多系统和厂商仍然保持了1 KB=1024 Bytes的表示方式,并没有附上"i". 内存方面的JEDEC标准也仍然我行我素,采用了与Windows一样的表示方法,所以我们今天在内存上看到的GB、MB等单位都是1024进位的. 而硬盘存储业界,仍然使用1 KB=1000 Bytes的国际单位制标准对容量进行描述.
1KB = 1,000 Byte
1MB = 1,000 KB
1GB = 1,000,000 KB
1TB = 1,000,000,000 KB
1KiB = 1024Byte
1MiB = 1024KiB
1GiB = 1024MiB = 1048,576 KiB
1TiB = 1024GiB = 1073,741,824 KiB
**in short 标准单位中多了一个 'i' 则是1024进制**