拥塞控制
总的传输率 是一个木桶效应 取决于最短板
A发数据给B 的速度 取决于中间节点的最大传送速率
具体怎么衡量中间设备的转发能力进行量化?
把中间的设备都看成一个整体
使用一个较小的窗口传输 如果传输通常 就调大窗口
使用一个较大的窗口传输 如果传输丢包出现拥堵 就调小窗口
拥塞窗口:在拥塞控制之下 采用的窗口大小
TCP中 拥塞控制具体是这样开展的
- 慢启动:刚开始时进行通信 会使用一个非常小的窗口
- 指数增长:在传输通畅的过程中 拥塞窗口就会指数增长
- 线性增长:指数增长当拥塞窗口达到一个阈值之后就会从指数增长 转换成线性增长
注意: 这里的指数增长和线性增长都是按照传输的轮次 限制给指定窗口大小是4000 发完400之后这一轮就完了 当收到ack之后就继续往下法术建议
- 拥塞窗口回归小窗口:当窗口大小增长过程中如果传输出现丢包 就认为当前网咯出现了拥堵 就会把窗口大小调整成最初的小窗口 继续回到之前 指数增长+线性增长的过程 另外此处也会出现根据当前出现丢包窗口的大小 调整阈值

实际发送方的窗口 = min(拥塞窗口,流量控制窗口)
拥塞控制和控制流量控制,共同限制了滑动窗口机制可以是滑动窗口能够在可靠性的前提下提高了传输效率 保证可靠性机制
延迟应答
提高传输效率的机制 在条件允许的基础上尽可能提高窗口大小
在需要返回ack的时候 拖延一点时间 利用延迟的这个时间 就可以给应用程序腾出来更多的消费数据的时间 接收缓冲区的剩余空间 就会更大了
例如
一个接收缓冲区有10kb此时已使用7kb此时返回的窗口大小就是3kb
如果等待500ms在返回ack有可能在这500ms之内应用程序又消费掉了2kb此时返回窗口大小就是5kb了 这就是延迟应答
捎带应答
在延时应答的基础上 引入第一个进一步提高效率的方式 基于延时应答让数据进行合并
客户端和服务器之间的交互 主要是一问一答的形式
主机A给主机B一个请求
主机B返回一个ack B又返回一个响应 主机 A 返回一个ack

捎带应答后

为什么说四次挥手可能是三次 主要就是延时应答和捎带应答 起到的效果
数据报从两个合并成一个 效率会有明显的提升
主要是因为每次传输数据是需要封装分用的
能合并的原因一方面是时机上可以同时 一方面是ack数据本身不需要携带载荷 和正常数据不冲突 完全可以让一个数据报 既能携带载荷数据 又能带有ack信息(ack标志位 窗口大小 确认序号)
面向字节流
粘包问题
通过 tcp read/write的数据都是tcp报文的载荷 也就是应用数据层 发送方一次性是可以发送多个应用层数据报的 但是接收的时候 如何区分 从哪里是一个完整的应用数据报? 如果没设计好 接收方就很难区分 甚至会产生bug 发送两个包 但是读可能读了半个或者一个半都会产生问题

站在发送发的角度预期aaa bbb ccc分别是三个应用层数据报
但是在接收方的应用程序 读取这里的数据read可能是一次读一个字节或者读若干个字节没有一次读取一个我们希望的一个应用层数据报

此处正确的做法是 设计合理的应用层协议
需要站在应用层角度 解决问题
- 应用层协议中 引入分隔符
例如 使用\n约定包之间的分隔符 - 应用层协议 引入包长度 能区分包之间的边界
例如使用前面固定两个长度作为单位
0x003aaa 0x003bbb
接收方读取数据的时候先读两个字节然后根据长度来读取后面的数据
接收方应用程序读取数据的时候就可以先读取两个字节得到包的长度 再根据长度读取后面的数据
粘包问题 不仅仅是tcp才有 只要是面向字节流的机制文件也有同样的问题 解决方法都一样 要么使用分隔符要么使用长度单位
TCP 异常情况处理
-
进程崩溃
进程没了->PCB没了->文件描述符表被释放->想到于调用socket.close()->崩溃的一方就会发出FIN 进一步触发四次挥手 此时连接就正常释放了 此时tcp处理和进程就正常退出 -
有一方主机关机(正常情况的关机)
正常关机先测试关闭所有的进程 强制终止进程 和崩溃的处理一样
主机关机会有一定的时间 在这个时间内四次挥手挥手正好 没有挥手完也不要紧
比如A主机关机 B主机的fin发不过去重传几次就会单方面释放自己的连接信息了 -
主机掉电
如果A主机掉电此时A无法给B发起任何FIN
a) 如果B正在给A发送消息(接收方掉电) B发的消息没有ackB就会触发超时重传重传仍失败 就会触发RST字段位1 尝试重置连接 重置操作仍然失败 此时就会继续单方面释放连接了
b) 如果A正在给B发消息(发送方掉电)
B在等A的消息 A突然不发消息了 B不知道A是等会就能继续发 还是不发了 B就会阻塞等待 具体等多久不知道
此处就涉及到"心跳包" B这边虽然是接收方 也会周期性给对方发起一个不携带任何业务数据tcp数据报 就是为了触发ack确认A是否正常工作 如果A不能正确反回ack就是说明A是挂了 -
网线断开
相当于主机掉电的升级版
网线断开就会导致A和B无法通信
发送方就会出现主机掉电的第一种情况
接收方就会出现主机掉电的第二种情况
TCP的十个核心特性
- 确认应答(可靠性)
- 超时重传(可靠性)
- 连接管理(可靠性)
- 滑动窗口(效率)
- 流量控制(可靠性)
- 拥塞控制(可靠性)
- 延时应答(效率)
- 捎带应答(效率)
- 面向字节流->粘包问题
- 异常处理情况->心跳包
关于TCP和UDP对比
TCP 优势在于可靠性 适用于绝大部分场景
UDP 优势在于效率 适合机房内部的主机之间通信(机房内部 贷款比较充裕不太容易遇到拥堵丢包的情况 有希望主机之间的通信速度能比较快)

- 4位版本号用来表示ip协议的版本现有的ip协议只有两个版本ipv4 ipv6
- 4位首部长度 设定和tcp一样ip报头可变长 ip报头又是带有选项的
- 8位服务类型 类似于切换型态
- 16位总长度 ip报头+载荷长度 总长度-ip报头长度=>载荷长度=>tcp报头总长度 tcp报头总长度-tcp报头长度=>tcp载荷长度
这里16位总长度涉及64kb的问题但是ip协议自身支持拆包组包机制 如果需要携带比较长的数据的适合ip协议会自动把一个数据源报拆成多个数据报接收方在进行分用的适合 也会把多个数据和并成一个数据报 - 16位标识 3位标志位 13位片偏移描述了整个ip数据报拆包组包的过程
当ip数据报需要携带比较长数据的适合就在ip协议这一层触发拆包操作把一个大包拆成多个小包 多个小的ip数据报都会带有ip报头 载荷是tcp数据报的几个部分 拆成的两个数据报16位标识是相同的 13位偏移不同的我们可以通过它区分那个在前 前一个更小后一个包更大 根据片偏移区分先后顺序 3标志位有一位是不用的 还有一位表示是否允许拆包 1为允许 剩下以为标记剩下一位是否是最后1位 0位最后一位 - 8位生存时间TTL
单位是次 初始情况下TTL会有这个数值(32/64/128)每经过一个路由器转发TTL就会-1减到0就会被弃用了 正常来说TTL足以支持数据报到达网络的任意一个位置 如果出现了0 证明目标ip不可达 - 8位协议
描述了上层 传输层 使用哪种协议 - 16位首部校验和
检验数据是否正确的机制 只需要首部即可 载荷部分 已经自己校验过了 - ip地址
网络上有这么多主机 ip地址iu是描述主机的具体位置
32位源地址
所谓的ip地址其实是一个32位的整数(4字节)
由于32位方式表示就会使这个地址变得很大 很难理解记忆一般都会把ip地址按照点分十进制的方式表示 使用 三个.把32位分成4个部分每个部分就是8位1个字节(点分十进制)
32位标识的数据量能表示42亿9千万 地址原则上不能相同(每个ip要不相同) 如今能上网的设备到达百亿级别了 所以ip地址不够用了怎么办?
动态分配ip(DHCP)
这个设备 不会一直需要上网 需要上网 就分配ip 不需要就先不分配
这种方案 只能缓解 不能根治
NAT机制(网络地址转换)
把ip地址分成两大类
内网ip:允许不同局域网内的设备 ,内网ip可以重复 同一局域网内的设备内网ip不能相同
此时大量的设备可以使用同样的ip但是是在不同的局域网中此时ip不够用就得到了很大改善
外网ip:外网ip不能重复
此时局域网的设备之间进行通信 肯定是ok的(局域网内部 内网ip都是唯一的)
A局域网中的设备 想和B局域网中的设备通信这个时候咋办?(但前很可能这两设备ip相同)
当前的规则 直接禁止!! 要想通信就需要用一个带有外网ip的设备进行中转
32位目的地址
局域网内部设备带有访问外网ip的设备
像平时使用的电脑手机 都是在局域网内部使用 他们会有一个内网ip 还有一类设备时"服务器" 服务器可以有外网ip 这个过程就涉及NAT工作过程:
我们发送一个数据报 经过电信路由器时 就会触发NAT机制 电信路由器 会使用自己的外网ip替换掉当前ip数据报中的源ip 当这个数据报到达目的服务器之后 服务器不知道数据报源自源主机 而是来自电信的路由器地址
NAT的机制下 意义就在于 一个外网ip代表的不一定时一个设备了 而是很多设备
那么目的服务器要怎么返回响应给源主机呢?
返回的数据报先返回给电信路由器 之前对于NAT设备(路由器)会在触发NAT的适合 维护一个映射表 如
| 替换前 | 替换后 |
|---|---|
| 源IP:端口号 | 替换ip:端口号 |
TCP/UDP报头中 还有端口号 此时我们就可以结合这张表查表知道替换前的ip进行转发 把目的ip替换回来
当前的互联网世界 就是通过NAT构建起来的
缺点
效率不高
非常繁琐
不方便直接访问局域网设备
提高了ip的地址利用率 并没有从根本解决IP不够用的问题
但有一个最大的优点使其得到广泛使用 NAT是一个纯软件实现发方案
ipv6从根本上解决ip地址不够用的问题
ipv4 四个字节 32位表示ip地址2^ 32
ipv6 是十六个字节128位表示ip地址2^32 ^32 ^32 ^32
其地址数量号称可以为全世界的每一粒沙子编上一个地址
为什么NAT能成功 ipv6发展起来很难呢
因为ipv6和ipv4不兼容 想要升级ipv6需要升级路由器 升级ipv6 也不会提高网速 但是NAT可以纯软件实现 成本低
ip地址分为两个部分
网络号:标识网段 保证相互连接的两个网段
主机号
例如一个IP地址 192.168.0.333
然后192.168.0是网络号 .333是主机号 如果两台主机的网络号相同就表示连接在同一个局域网
路由器的 WAN 192.1688.1.10 LAN 192.168.0.1
光猫 LAN 192.168.1.1
电视:192.168.1.11
此时路由器就起到了一个连接作用 电脑路由器是一个局域网 同一个局域网中的网络号必须相同 足迹好必须不同
两个相邻的局域网通过路由器连接 网络号 必须不同
一个ip地址 那个部分是主机号 那个部分是网络号?
通过子网掩码 来识别

子网掩码 左侧必须是连续的1 右侧必须是连续的0 (0和1不能穿插)
1的范围就描述了ip地址的对应哪些是网络号
前24bit是网络号 8bit是主机号
子网掩码是现代划分网络号的方案
以前还使用ABCDE类划分网络号

特殊的ip地址
广播ip
将ip地址中的主机地址全部设为0 就成为了 网络号 代表这个局域网
例如
192.168.0 255.255.255.0
如果ip地址是192.168.0.255 这个就属于广播ip 往这个ip地址发送数据报 就会被转发给局域网中的所有设备
应用场景 投屏软件 就可以把手机投屏上电视(前提是手机 电视都在同一个wifi下)手机点击搜索设备时 就会把电视显示出来 这个搜索过程就是基于广播ip (广播地址只能使用udp 而不能使用tcp tcp无法针对广播地址进行三次握手 建立连接操作)
本机环回ip
127.0.0.1
本机和本机通信就可以使用这个ip
localhost也可以表示本机 是一个域名会被解析成127.0.0.1
本文详细介绍了TCP拥塞控制机制,包括慢启动、拥塞窗口管理、流量控制、延时应答和捎带应答,以及如何处理粘包问题。同时讨论了NAT在网络中的作用和IPv6的发展挑战。

被折叠的 条评论
为什么被折叠?



