网络基础-传输层, 网络层数据链路层
个人笔记纪录, 待完善
计算机之间通讯的基础
- 需要得知对方的IP;
- 最终根据MAC地址(网卡地址), 输送数据到网卡, 由网卡接受;
- 通过ARP广播获得MAC地址;
- Ping实用的ICMP协议(首先通过ARP广播获取MAC地址);
同轴电缆: 半双工通讯;
集线器: 类似同轴电缆, 半双工通讯;容易冲突;
网桥: 两个接口, 通过自学习记录每个接口侧的mac
地址;从而起到隔绝冲突域的作用;
交换机: 相当于接口更多的网桥, 全双工通讯;
路由器: 可以在不同网段之间发送数据, 隔绝广播域;
MAC地址的获取
- 当不知道对方MAC地址时候通过
ARP
广播获取对方的MAC
地址;
- 获取成功后会缓存
IP
地址MAC
地址的映射信息; 称为ARP
缓存 - 通过
ARP
广播获取的MAC
地址属于动态缓存(dynamic
);存储时间比较短一般是两分钟, 过期了就自动删除;
- 相关命令:
-
arp -a[主机地址]
:查询ARP
缓存; -
arp -d[主机地址]
: 删除ARP
缓存; -
arp -s 主机地址 MAC地址
:增加一条缓存信息(这个属于静态缓存, 存储时间比较久, 不同的系统存储时间不同); -
ipconfig/all
:查看MAC地址.
IP地址的组成:
IP地址有两部分组成: 网络标识(网络ID, 网段), 主机标识( 主机ID);
- 同一网段的计算机网络ID相同;
- 通过子网掩码(subnet mask)可以计算出网络ID:子网掩码&IP地址;
如何避免浪费IP资源?
- 合理的子网划分
信道:信息传输的通道, 一条传输介质上(比如网线), 可以有多条信道;
单工通信: 信号只能往一个方向传, 任何时候不能改变信号的方向;
比如无线电广播, 有线电视广播;
半双工通信:信号可以双向传播, 但是必须交替进行, 同一时间只能往一个方向传播;
比如对讲机
全双工通信:信号可以同时双向传播;
比如手机
数据帧:数据链路层

如何确保一个数据帧的完整性:
帧的尾部有FCS标识符是根据帧首和帧尾计算得来的, 在获得一个帧数据后帧首帧尾根据计算计算如果值等于FCS则数据帧完整, 去掉帧首帧尾即可获得中间的数据buffer;
数据链路层的数据(MTU)大小为不超过1500个字节,因此我们可以推断出传输层的数据段最大为不超过1460字节;(网络层的首部最小20个字节, 传输层首部最小20个字节, 因此传输层的数据段最大为1460);
- 传输层- 数据段 segment;
- 网络层- 数据包 package;
- 数据链路层- 数据帧 frame;
ping
的几个用法:
- ping/? : 查看ping的用法
- ping ip地址 -l 数据包大小 : 发送指定大小的数据包;
- ping ip地址 -f : 不允许网络层分片;
- ping ip地址 -i TTL : 设置TTL的值;
通过tracert, pathping ip地址的方式, 可以查看途径的路由器;
TTL : Time To Live(生存时间) 每经过一个路由器值就会减1; 为0时数据包不再传输;
端口:
UDP首部中端口是占用2个字节(因此其取值范围是0-65535);
防火墙可以可以设置开启/关闭某些端口提升安全性;
常用命令:
- netstat -an : 查看被占用的端口;
- netstat -anb : 查看被占用的端口, 以及占用端口的程序;
- telent 主机 端口 : 查看是否可以访问主机的某个端口;
打开telent功能: 控制面板-程序-启用或关闭Windows功能-勾选telent
功能-确定;
传输层的两个协议
TCP: 传输控制协议;
UDP: 用户数据报协议;
对比 | TCP | UDP |
---|---|---|
连接性 | 面向连接 | 无连接 |
可靠性 | 可靠传输, 不丢包 | 不可靠传输, 尽最大努力交付, 可能丢包 |
首部占用空间 | 大 | 小 |
传输速率 | 慢 | 快 |
消耗资源 | 大 | 小 |
应用场景 | 浏览器, 文件传输, 邮件 | 音视频通话, 直播 |
应用层协议 | HTTP, HTTPS, FTP, SMTP, DNS | DNS |
- TCP
TCP的数据格式:

TCP标志位的作用:
-
URG(Urgent):
当URG为1的时候 紧急指针字段才有效, 表明当前报文中有紧急数据, 需要优先传输; -
ACK(Ackowledgement)
: 当ACK为1的时候确认号字段才有效; -
RST(Reset)
: 当RST为1的时候表明链接中出现严重差错, 必须释放链接, 然后重新建立链接; -
SYN (Synchronization)
: 当SYN=1, ACK=0时表示这是一个建立链接的请求; 若对方同意建立链接则回复SYN=1, ACK=1; -
FIN(Finish)
: 当FIN=1时表示数据传输完成, 要求释放链接; -
序号(Sequence Number)
: 占用4个字节, 建立链接后, 确认号代表: 期望对方下一次传过来的TCP数据部分的第一个字节的编号; -
窗口(Window)
: 占2个字节, 这个字段拥有流量控制功能, 用于告知发送方下一次发送的数据的允许大小(字节为单位)
1. 可靠性传输:
如果数据超时或者收到三次确认都会重新发送保证数据完整性;
主要是通过ARQ(自动重传技术-超时重发)+滑动窗口协议实现(例如一次可以接收4个数据包, 就是一个缓冲区的设置);
另外通过SACK(选择性确认)来告诉发送方哪些数据已经接收到哪些数据丢失, 这样TCP就只发送丢失的部分即可;
2. 流量控制
如果接收方的数据缓冲区已经满了, 而发送方还在不停的发数据, 则需要进行流量控制;如果不进行控制则接收方只能将大量的数据包进行丢弃, 造成的大量的网络资源浪费;
什么是流量控制?
让发送方的发送速度不要太快, 让接收方有足够的时间和空间来处理和接受数据;注意这个概念是指点对点之间;
原理:
通过确认报文中的窗口字段来控制发送方的发送速率;
发送方的发送窗口大小不能超过接收方的窗口大小;
当发送方收到接收方的窗口为0时则不再发数据;
特殊情况:
刚开始接收方发送了0窗口报文给发送方, 然后发送方停止了发送数据;
后面接收方有空间了, 发送了非0窗口报文给发送方结果报文丢失了;
则接收方和发送方陷入循环;
解决方案: 发送方收到0窗口报文的时候停止发送数据, 同时开启一个定时器, 隔一段时间发送测试报文取询问接收方窗口的大小, 如果仍然收到0窗口报文则重新刷新启动定 时器;
3. 拥塞控制

链路的吞吐量在过载的时候会导致拥塞;直观的理解为, 一条路可以同时供100辆车100km/h通过, 但是当有200辆车的时候估计只能以50km/h通过, 当有300辆车时估计会堵的动不了;
拥塞控制是指避免过多的数据注入到网络中, 避免网络中的路由器或者链路过载;拥塞控制是一个全局性的过程, 涉及到所有的主机, 路由器; 是大家共同努力的结果; 注意区分流量控制是点对点之间的;
几个缩写:
MSS: 每个段最大的数据部分大小, 在建立链接是确定;
swnd: 拥塞窗口;
rwnd:接收窗口;
swnd:发送窗口; swnd=min(swnd, rwnd);
拥塞控制思路:
慢开始(慢启动)-拥塞避免- 快速重传-快速恢复;
a. 慢开始:
- cwnd的初始值比较小, 然后随着数据包被接收方确认(收到ACK), cwnd就会成指数级增长(每次是前一次的2倍);
b. 拥塞避免:
- ssthresh:慢开始阈值,cwnd达到阈值后以线性方式增长, 拥塞窗口缓慢变大, 防止网络过早的出现拥塞,
- 乘法减小:一旦网络出现拥塞(出现丢包, 丢包后会开始快重传发送三个确认字符), 则把ssthresh的值减为拥塞峰值的一半, 同时执行慢开始算法(cwnd恢复到初始值) , 当网络频繁出现拥塞时ssthresh值会下降的很快;
c. 快重传:
- 接收方: 每收到一个失序分组立即发送重复确认, 使发送方知道有数据没有送达, 而不再等待自己发送数据时才进行确认;
- 发送方: 只要连续收到3个确认字符(一共4个相同的确认)就立即发送分组中丢失的数据, 而不再等待重传计时器到期再进行重传;
d. 快恢复:
- 当发送方连续收到3个重复确认说明出现网路拥塞丢包了, 就执行乘法减小, 把ssthresh的值减为拥塞峰值的一半;
- 与慢开始不同, 新的机制在拥塞后不再执行慢开始(即cwnd不再恢复到初始值), 而是把cwnd设置位新的ssthresh值(减小后的)然后开始执行加法增大使拥塞窗口缓慢线性增大;
e. 用图片表示拥塞控制

4. 三次握手

状态解读:
Closed:
Client处于关闭状态;
Listen:
Server处于监听状态, 等待Client链接;
SYN-RCVD:
表示Server收到SYN报文, 当收到Client的ack报文后进入ESTABLished状态;
SYN-SENT:
表示Client已经发出SYN-SENT报文, 等待Server的第二次握手;
ESTABlished:
已经建立链接;
TCP建立链接前两次握手的特点:
- SYN都是设置为1;
- 数据部分的长度都为0;
- TCP的头部长度一般都是32字节, 固定部分20字节, 选项部分12字节;
- 双方会确认交换一些信息(选项部分的那12字节里面): 比如MSS, 是否支持SACK, 窗口缩放系数;
ACK和ack的区别:
大写的ACK(Acknowledgement)是标识位, 可以通过它标识包的性质, [ACK] or [SYC] or [FIN] .
小写的ack(Acknowledgement Number), 是确认号。 即收到seq=x 的数据包后,回复 ack=x+1 的确认。
5. 四次挥手

状态解读
FIN-WAIT1:
表示向主动断开, 向对方发送了FIN报文后进入FIN-WAIT1状态;
CLOSE-WAIT:
表示等待关闭, 当对方发送FIN报文给自己,会回应一个ACK报文, 同时进入CLOSE-WAIT状态, 此状态下如果仍然有数据发送给对方则会继续发送, 如果没有数据发给对方,则发送FIN给对方;
FIN-WAIT2:
主动方收到对方的ACK报文后就会处于FIN-WAIT2状态然后等待对方的FIN报文;
LASK-ACK:
被动一方在发送FIN报文后处于LAST-ACK状态, 收到主动方的ACK报文后就进入CLOSED状态;
TIME-WAIT:
主动方收到对方的FIN报文后回复ACK报文给对方并进入TIME-WAIT状态, 等待2MSL时间后进入CLOSED状态;
如果在FIN-WAIT1状态下同时收到对方的FIN和ACK报文则直接进入TIME-WAIT状态, 无需经过FIN-WAIT2状态;
CLOSED:
关闭状态;
CLOSING:
一种比较罕见的状态, 表示发出FIN报文后没有收到对方的ACK报文反而也收到了FIN报文,即双方几乎同时发送FIN报文时就会进入CLOSING状态;表示双方都在进行关闭链接;
细节补充
- TCP/IP协议栈在设计上允许任何一方申请断开链接;
- Client发送ACK报文后会有一个TIME-WAIT阶段, 在等待一段时间后才会正式断开连接;
一般等待时间时2MSL(Maximum Segment Lifetime最大分段生存期),
a. MSL表示TCP报文在Internet上的生存时间;
b. 每个TCP的具体实现都需要选择一个确定的MSL值, RFC-1122推荐的时间是2分钟;
c. 可以防止本次链接中产生的数据包误传到下一次链接中, 因为本次链接中的数据包会在2MSL时间内全部消失;
- Client发送ACK报文后会有一个TIME-WAIT阶段, 在等待一段时间后才会正式断开连接;
- 通过抓包时断开链接有时候只能看到3次挥手, 原因如下: 在Server端收到FIN报文后确保自己不再有数据要发给Client则会将2, 3次挥手合并;告诉Client两个事情
a. Server端不再有数据发送给Client;
b. Server知道Client不再有数据发给自己;
- 通过抓包时断开链接有时候只能看到3次挥手, 原因如下: 在Server端收到FIN报文后确保自己不再有数据要发给Client则会将2, 3次挥手合并;告诉Client两个事情
题目
1. 为什么 要将数据在传输层切片而不是在网络层切片后交给数据链路层?
为了提高重传的性能; 可靠性传输是在传输层进行控制的;
- 如果不在传输层进行分段, 一旦数据出现丢失, 则整个传输层的数据都要重新传递;
- 在传输层分段后, 一旦数据出现丢失, 则直将丢失的数据部分重新传输即可;
2. 如果一个数据包传送了好几次仍然失败会一直尝试传输直到成功么?
这个取决于系统的设置, 例如有些系统在重新传输5次后仍然不能成功, 就会发送reset报文(RST
)断开TCP链接;
3. 为什么TCP链接需要三次握手? 改成两次行不行?
三次握手的目的: 防止服务器端一直等待, 浪费资源;
如果改成两次握手会出现的情况: 假如client客户端第一次发送的请求报文段, 因为网络延迟的原因, 在释放链接后才到达服务器端, 本来这是一个应该失效的请求链接, 但是server端收到这个请求后会误认为这是client发送的新的链接请求, 于是sever端就会再次给client发送确认报文然后建立链接, 等待client发送数据过来, 这样的话, server端就会一直处于链接状态等待;
采用三次握手的方法可以防止上述情况发生:例如上述情况, client没有向server发出确认, server端收不到确认就知道client不是建立链接;
另一种解析的思路: client和server建立链接是为了相互交换数据, 所以得确保自己和对方的数据收发功能都处于正常状态;
第一次握手: server端可以确认自己的接收功能和client端的发送功能正常;
第二次握手: client端可以确认自己的发送和接收功能都是正常, 并且server端的接收和发送功能都是正常的;
第三次握手: server端确认自己的发送功能和client的接收功能正常;;
4. 如果TCP建立链接时的第三次握手失败了怎么办?
第三次握手的时候server处于SYB-RCVD状态, 如果等不到client端的ACK, server端会再次发送ACK+SYN包, 如果多次发送后仍然等不到client的ACK包, 则server端发送RST包, 强制断开链接;
5. TCP断开链接时的四次挥手TIME-WAIT阶段是否有必要?
有必要, 而且不能省去, 原因如下: 假如Client在发送ACK报文后立即进入了断开状态, 然后因为网络状态Server端没有收到这个ACK报文则会重发FIN报文给Client, 则可能会出现的情况如下:
a. Client端没有反应, Server重复尝试发送FIN给Client, 浪费资源;
b. Client刚好有个新的应用分配了同一个端口, 新应用本是想建立链接, 结果收到FIN报文后就会进入断开链接操作;
e