应用层

自定义数据组织格式:
1. 行文本
**2.xml(标签):**比较原始,可读性好,冗余较多
<request> <userId>1000</userId> <position>USA</position> </request>**3. json:**主流方式,可读性好,冗余一般
{ "userId":1000, "position":"USA" }**4. protobuf:使用二进制,**高性能场景下使用的方式,可读性差,冗余最小
现成的协议:
FTP:文件传输
SSH :远程操作主机
telnet:网络调试工具
HTTP:协议
.....
DNS
DNS是一整套从域名映射到主机的系统 ,TCP/IP使用IP地址 来确定网络上的一台主机或一个程序 ,但是IP地址不方便记忆。于是人们就发明了域名 ,域名是一个字符串,并且使用Hosts 文件来记录域名和IP的映射关系。随着网络的发展,每天都有数以万计的网站建立,也有数以万计的网站消失,所以无法在本地实时维护Hosts 文件。于是就演化出了域名服务器,通过访问域名服务器来获取对应的IP地址。
DNS是应用层协议 ,底层使用UDP 进行解析,浏览器也会对DNS的结果进行缓存
传输层
UDP协议
协议端格式

长度属性:16bit位 ,表示UDP最大可以传输64KB内容
校验和: 使用CRC校验和 ,把数据包每个字节都当成一个整数相加,最后的结果就是校验和。如果校验和出错,直接舍弃
UDP特点
无连接: 知道对端的IP和端口号就可以直接进行传输,不需要建立连接(对端没有保存发送端的信息)
**不可靠:**没有确认机制,也没有重传机制,发送之后就不管看
面向数据报: 不能够灵活控制读写的次数和数量,发送一个100字节的报文 ,只能一次接收100字节,不能10字节接十次
基于UDP的应用层协议
NFS:网络文件系统
TFTP:简单文件传输协议
DHCP:动态主机配置协议
BOOTP:启动协议,用于无盘启动
DNS:域名解析协议
TCP协议

1. 32位序号/确认序号: 保证数据不丢失,不乱序,不重复
2. 首部长度: 标识该TCP报头有多少个32bit(四字节) ,所以TCP头部长度 最大值是 15*4=60字节
3. 6位标记位:
URG:紧急指针是否有效
ACK:确认号是否有效
PSH: 提示接收端应用程序立刻从TCP缓冲区把数据读走
SYN:请求建立连接 ,携带SYN标识的称为同步报文段
FIN: 通知对端,本端要释放连接 ,称为结束报文段
4. 16位校验和:发送端填充(包含头部和载荷),接收端校验不通过,则舍弃
5. 16位紧急指针: 标识哪部分数据是紧急数据,直接从某个指定的序号读取
确认应答机制(ACK)
保证数据不丢失,不乱序,不重复
为确保TCP字节流传输的顺序,避免后传先至的问题,TCP为载荷中每个字节的数据 都进行了编号,当接收方接收到数据之后,会知道这个数据的起始编号(32位序号SN) ,根据载荷长度 ,可以计算出下一个数据 的起始编号,在返回给发送方的TCP报头中的32位确认序号中,标记这个数据
如果1001编号的数据,比0编号的数据先到,read()也不会读数据,而是等0号数据到达,在"接收缓存区"排好序之后 ,在进行读操作

超时重传
如果发送方达到一定时间 ,还没有收到ACK ,那么发送方会认为发生了丢包 ,这时就会进行重传
发送方无法区分是数据丢失还是ACK丢失 ,都会触发重传操作。如果是因为ACK丢失造成了重传,那么"数据缓冲区"也会进行一次去重操作
通过确认应答和超时重传 保证了TCP的可靠传输
连接管理
这里的连接表示通信双方保存对方的信息
建立连接(三次握手):
服务器启动,调用系统Listen api, 进入监听状态
1. 客户端调用connec t系统调用,发送SYN报文 (SYN=1 ,携带客户端初始序列号ISN(c) ),进入SYN_SENT状态
2. 服务器 收到客户端的SYN报文,返回SYN + ACK报文 (SYN=1,ACK=1,确认字号段=c+1 ,携带服务器初始序列号ISN(s) ),发送之后进入SYN_RCVD状态
3. 客户端收到SYN+ACK报文,发送ACK报文 (SYN=0,ACK=1,确认字号段=s+1),发送完变为ESTABLISHED 状态。服务器收到客户端的ACK,进入ESTABLISHED状态,全双工的TCP连接成功建立
ESTABLISHED:连接建立完毕,随时可以发送数据

目的: 为了确保网络连接正常 ,客户端与服务器的发送能力和接收能力均正常 ,以及协商数据
断开连接(四次挥手)
1. A给B发送FIN报文 ,表示准备断开连接 ,发送之后进入FIN_WAIT_1状态
2. B 收到FIN报文,向A返回ACK应答报文 ,进入CLOSE_WAIT状态
3. B 调用socket.close() 方法,向A发送FIN报文 ,进入LAST_ACK状态
4. A 收到FIN,向B发送ACK应答报文 ,B收到ACK应答报文后,关闭通信 。A经过TIME_WAIT状态后,也关闭通信
CLOSE_WAIT :**等待应用层调用socket.close()**关闭连接的状态
TIME_WAIT: 等待时间为2*MSL(TCP报文最大生存时间)
1. 保证在两个传输方向上的尚未被接收到的或是迟到的报文都已消失(否则服务器立即重启,可能会接收到上个进程的数据)
2. 在理论上保证最后一个报文可靠到达 (假设最后一个ACK出现丢包,B会对重传FIN报文,此时A处于TIME_WAIT 状态,接收到FIN报文后可以重发ACK)

A发送FIN仅关闭了A -> B的通道 ,A仍可接收B的数据
B发送FIN才关闭B->A的通道
滑动窗口
对于每发送一次数据段,都要给一个ACK确认应答,收到ACK后才能传输下一个数据。这样虽然安全,但是性能比较差 。我们可以一次发送多条数据,这样可以大大提高性能。

窗口大小:无需确认应答而可以继续发送确认应答的最大值 ,上图的窗口大小就是4000字节
1. 发送前4个数据时,无需等待ACK,直接发送
收到第一个ACK后 ,继续发送第五段数据
操作系统会开辟发送缓冲区 来记录当前还有哪些数据没有应答 ,只有确认应答过的数据, 才能从缓冲区删掉
可能会出现的问题
1. 数据报已到达,ACK被丢了: 不用处理,因为可以通过后续的ACK进行确认
2. 数据报丢失: 接收端会一直发送ACK =1 的应答报文 ,来索取1~1000的数据报 。当收到1~1000的数据报,返回的就是4001。因为1001~4000的数据已经收到,并存放到接收缓冲区中
这种机制也称为快速重传
流量控制
接收端处理数据的速度是有限的,如果发送端发的数据太快,导致接收端的接收缓冲区被装满。这个时候再次发送,也没有任何意义。因此TCP支持根据接收端的处理能力 来动态决定发送端的发送速度 。这个机制就是流量控制
接收端可以将自己接收缓冲区剩余的空间大小 放入 TCP报头的窗口大小字段 。通过ACK来告知发送端
通过接收到的窗口大小字段,发送方就会动态调整发送速度 。当窗口大小字段为0 时,表示接收方接收缓冲区已满 ,发送方停止发送数据
之后,发送方每隔一段之间会发送一个窗口探测包 ,用来获取接收端此时的可用接收缓冲区大小
TCP首部40字节的选项中还包含了一个窗口扩大因子M ,所以实际窗口大小可以是 窗口字段的值<<M位 ,也就是乘以2^M
拥塞控制
TCP引入慢启动机制:
先将窗口大小设置为1 ,然后窗口大小再指数级增长
增长到ssthresh初始值 ,再成倍数增长 ,直到出现丢包
出现丢包后,将窗口大小设置为一个新的ssthresh值 ,然后继续成倍数增长
少量的丢包,只是触发超时重传,大量丢包才认为是网络堵塞

流量窗口和拥塞控制 都是TCP协议想尽可能快的把数据传输给对方,两者取小值
延迟应答
接收方通过延时返回ACK应答 ,利用这段时间消耗接收缓冲区中的数据 ,最终只返回最后一次的ACK报文。这样窗口越大 ,网络吞吐量就越大,传输效率就越高
**数量限制:**每隔N个包就应答一次
**时间限制:**超过最大延迟时间就应答一次
捎带应答
在延迟应答的基础上,可以将ACK和响应一同返回。
面向字节流
创建一个TCP的socket,同时在内核里会创建一个发送缓冲区和接收缓冲区 。调用write时,数据会先写入到发送缓冲区 中。接收数据也是从接收缓冲区中拿数据。
TCP的一个连接,既有发送缓冲区 ,又有接收缓冲区 。既可以读数据 ,又可以写数据 ,这个概念称为全双工
粘包问题
粘包问题的包是应用层的数据包 ,在TCP的协议头中,没有报文长度标识。站在传输层角度,TCP是一个一个报文过来的,按照序号排好序放在缓冲区里。占在应用层角度,看到的只是连续的字节数据 。不知道从哪开始,从哪结束
对于定长的包 ,保证每次都按固定大小读取
对于变长的包 ,可以在包头位置约定一个包总长度的字段 ,或者可以在包和包之间使用明确的分隔符
异常情况
进程终止:
进程终止/机器重启: 释放文件描述符表,仍然可以正常发送FIN,和正常关闭没有区别
机器掉电:
接收方突然掉电:发送方 接收不到ACK,首先会触发超时重传 。超时重传达到一定次数,就会触发**"重置TCP连接"** ,发送方发送复位报文 。如果复位报文还是没有ACK,那么发送方只好单方面释放连接
发送发突然掉电: 接收方不清楚发送方是掉电了,还是暂时没有数据发送。等到一定时间,接收方会发送一个**"心跳包"(周期性发送)** ,不携带业务数据,只是为了触发ACK。如果没有ACK响应,接收方就会释放连接
网络层
地址管理: 使用IP地址这样的概念,标识网络上某个设备的位置
路由选择: 在两个通信节点之间,规划出一个合理的路径
IP协议
主机: 配有IP地址 ,但是不进行路由控制设备
路由器: 即配有IP地址 ,又能进行路由控制
节点:主机和路由器的总称
协议头格式

1. 四位版本号: 指定IP协议的版本,对于IPv4就是4
2**. 4位头部长度:** 标识该报头有多少个32bit(四字节) ,所以头部长度最大值是15*4=60字节
3. 8位服务类型: 三位优先权字段(已弃用)4位TOS字段,和1位保留字段(必须置为0),4. 4位TOS分别表示:最小延迟,最大吞吐量,最高可靠性,最小成本。这四种相互冲突,因此只能选择一个。
5. 16位总长度: IP数据报整体占用多少字节
6. 16位标识ID:
拆包: 把拆出来的包设置为相同的ID
组包: 把相同标识的数据包组合到一起
13位分片偏移:
表示当前分片在原报文中处在哪个位置,实际偏移的字节数是这个值*8得到的
3位标志字段:
第一位保留位,第二位 设为1表示不分片 ,如果分片的话,第三位 置为1,其余 两位置为0
7. 8位生存空间: 一个IP数据报,能够在网络上传输的最大时间 ,单位是次数。IP数据报每次经过一个路由器转发一次,TTL-1,TTL减为0还无法到达,则会被丢弃。
8. 8位协议: 表示上层协议的类型
9. 16位头部校验和: 使用CRC进行校验,来鉴别头部是否损坏
地址管理
网段划分
将一个IP地址分为两个部分,网络号+主机号
网络号: 保证相互连接 的两个网段 内具有不同的标识
主机号: 同一网段内 ,主机之间 具有相同的网络号,不同的主机号
不同子网就是将网络号相同的主机放到一起
DHCP技术: 自动给子网内新增的主机节点分配IP地址
网段划分方式:CIDR
引入一个额外的子网掩码(32位正整数) 来区分网络号和主机号
子网掩码前几位都是1 ,最后几位都是0 ,将IP与子网掩码进行按位与操作 ,得到的结果就是网络号。
家用网络前24 位为网络号 ,后8位为主机号 ,子网掩码就为255.255.255.0
也可使用IP/N 来简洁表示IP地址和子网掩码 198.168.0.1/24
私有IP和公网IP
如果一个组织内部组建局域网,IP地址只用于局域网内通信,而不直接连到Internet上。局域网内的所有设备使用同一个公网IP ,互相之间使用不同的私有IP
私有IP格式:
10.*172.16.到172.31.
192.168.*
包含在这个范围内的都称之为私有IP,其余称之为公网IP
路由器
一个路由器有两个IP地址 ,一个是WAN口IP ,另一个是LAN口IP(子网IP)
通过LAN口连接的设备,都属于在同一子网中。
每一个家用路由器,又作为运营商路由器子网 中的一个节点,这样的运营商路由器可能会有很多层级,最外层的运营商路由器的WAN口就是一个公网IP

特殊IP地址
主机号全部为0 :网段,代表整个局域网
主机号全部为1 :广播地址 ,给同一子网中所有的主机 都发送数据包,必须通过UDP进行传输,TCP不支持广播
127.* :用于本机环回测试 ,通常为127.0.0.1
IP地址的数量限制
IP地址是一个四字节 的正整数 ,最大只能表示43亿左右个IP地址。
**1. 动态分配IP地址:**只给接入网络的设备分配IP地址,同一个MAC地址的设备,每次上网得到的IP地址不一定是相同的
2. NAT技术: 全称是网络地址转换技术
**1.**同一局域网下,设备A访问设备B,IP本身不重复,NAT不起作用
**2.**公网设备A访问公网设备B,IP本身不重复,NAT不起作用
- 不同局域网的设备A访问设备B,NAT不允许
**4.**公网设备A访问局域网设备B,NAT不允许
**5.**局域网设备A,访问公网设备B,NAT起作用:
局域网设备访问公网设备,触发网络地址映射 ,将局域网IP映射为路由器的公网IP ,通过这个公网IP对公网设备进行访问。如果局域网内,两个私有IP不同端口号不同 的设备访问同一个公网IP,经过网络地址映射,得到的公网IP相同,相互之间使用端口号 区分。对于局域网内两个私有IP不同,端口号相同的设备,则通过网络端口映射,映射为不同的端口。
通常来说,家里的局域网IP会先转换为路由器的WAN口IP ,通过这个WAN口IP 访问运营商服务器 ,逐层替换 ,最后变为公网IP
**3. IPv6(终极方案):**IPv6使用16字节128位的整数来表示IP地址,完全够用
路由管理
简单来说就是问路的过程,路由器通过维护路由表 来进行数据包的转发。当收到数据包时,路由器会提取目的IP地址 ,并于路由表中的网段进行最长匹配 。如果匹配成功,则转发给对应的 下一跳。如果所有的网段都不匹配,则按照默认路由转发 (默认网关,也就是上一级路由器)。
数据链路层
以太网不是一种具体的网络而是一种技术标准 ,既包含数据链路层 ,又包含物理层 。但凡是使用网线 上网的设备,走的都是以太网协议
MAC地址 (网卡的硬件地址):长度是48位,每个网卡都有一个唯一的MAC地址,是网卡出厂时确定的
IP与MAC的区别:
IP:描述路途总体的起点和终点
MAC:路途上每个区间的起点和终点,每经过一个节点,MAC地址都会改变
- 通过不同类型来区分载荷的格式,
