深度解析TCP/IP
- 1 应用层
- 2 传输层
-
- 2.1 端口号
- 2.2 UDP协议
-
- 2.2.1 UDP的特点
- 2.2.2 面向数据报
- 2.2.3 UDP缓冲区
- 2.2.4 UDP注意事项
- 2.2.5 基于UDP的应用层协议
- 3 TCP协议
-
- 2.3.1 TCP1大核心和8大特性
-
- 特性1:==确认应答(核心机制)==
- 特性2:超时重传
- 特性3:连接管理
- 特性4:滑动窗口
- 特性五:流量控制
- 特性六:拥塞控制
- 特性七:延迟应答
- 特性八:捎带应答
- 2.3.2 粘包问题
- 2.3.3 TCP异常情况
- 2.3.4 基于TCP应用层协议
- 2.3.5 小结TCP
- 2.4TCP/UDP对比
- 3 网络层
-
- 3.1 IP协议
-
- 3.1.1 头格式
- 3.1.2 网络划分
- 3.1.3 私网IP地址
- 3.1.4 路由
- 4 数据链路层
-
- 4.1 以太网
-
- 4.2 MAC地址和IP地址
- 4.3 MTU
- 4.4 ARP协议
- 5 物理层
- 6 补充重点
-
- 6.1 DNS
- 6.2 浏览器中输入url后, 发生的事情
- 6.3 NAT技术
1 应用层
针对特定应用的协议
简单的说就是咱们的程序这一层 (SSH、SFTP、HTTP、DNS解析域名),是为了实现程序去用的
2 传输层
2.1 端口号
端口号作用:找到应用程序
(1)知名端口号:知名程序在启动之后占用的端口号(0-1023)
- SSH服务器, 使用22端口
- FTP服务器, 使用21端口
- TELNET服务器, 使用23端口
- HTTP服务器, 使用80端口
- HTTPS服务器, 使用443
(2)动态端口号:1024-65535 最大端口号
两个程序不能使用同一个端口号,一个程序可以使用两个端口号
(理解:程序 – >人 ;端口号 --> 手机号)
2.2 UDP协议
16位源端口号:源程序的端口号,根据这个端口号可以定位到发送端程序
16位目标端口号:目标端口号,定位接收端的应用程序
16位UDP长度 = UDP头部长度 + 数据长度
16位效验和:效验数据的正确性
效验和的执行逻辑:
假设效验和的算法是MD5,MD5(UDP头部信息+UDP数据)
发送端就会将UDO所有内容发送给接收端,此时接收端就有了UDP的效验和所有数据,接收端就可以根据MD5(UDP头部信息+UDP数据),得到一个正确的效验和,然后用这个正确的效验和UDP头部信息中的效验进行对比,如果相等则表示数据是正确的,否则数据就是错误的,直接舍弃。
2.2.1 UDP的特点
- 无连接: 知道对端的IP和端口号就直接进行传输, 不需要建立连接
- 不可靠: 没有确认机制, 没有重传机制; 如果因为网络故障该段无法发到对方, UDP协议层也不 会给应用层返回任何错误信息
- 面向数据报: 不能够灵活的控制读写数据的次数和数量
2.2.2 面向数据报
应用层交给UDP多长的报文, UDP原样发送, 既不会拆分, 也不会合并
用UDP传输100个字节的数据:
如果发送端调用一次sendto, 发送100个字节, 那么接收端也必须调用对应的一次recvfrom, 接
收100个字节; 而不能循环调用10次recvfrom, 每次接收10个字节;
2.2.3 UDP缓冲区
UDP只有接收缓冲区,并没有发送缓冲区
- UDP必须要有接收缓冲区,可以大大提高UDP的工作效率
- UDP之所以不需要要发送缓冲区,是因为UDP是不需要连接的,也就是不需要等待对方先连接的,所以最快的佛南工作方式就是拿到消息就发
TCP和UDP都是全双工的
- 全双工:发送端或者接收端既可以发送消息,又可以接收消息
- 半双工:发送端只能发送消息,不能接收消息
2.2.4 UDP注意事项
因为UDP头部中有一个16位的长度(数据+头部),因此一个UDP的最大包必须是16位可以表示的。
所以UDP理论可以传输的大小为64K
如果UDP编程的数据包大于64K的解决方案:
- 在应用层进行数据包的拆分和组合(程序员定义)
- 不进行手动处理,交给TCP/IP协议去处理,他会在网络层进行分包和组包
实际工作中,会采取第一种(应用层组包和分包来实现UDP大数据的传递),因为如果使用了第二种方式,那么任意一个包丢失之后,那么整个数据包也丢失了,风险极大(网络环境非常复杂),因此不会选用第二种方式。
2.2.5 基于UDP的应用层协议
- NFS: 网络文件系统
- TFTP: 简单文件传输协议
- DHCP: 动态主机配置协议
- BOOTP: 启动协议(用于无盘设备启动)
- DNS: 域名解析协议
3 TCP协议
- 源/目的端口号: 表示数据是从哪个进程来, 到哪个进程去
- 32位序号/32位确认号
- 4位TCP报头长度: 表示该TCP头部有多少个32位bit(有多少个4字节); 所以TCP头部最大长度是15 * 4= 60
- 6位标志位:
URG:表示紧急消息
ACK:确认应答表示
PSH:用来表示让接收端将消息从缓冲区取走
RST:复位标识符
SYN:同步标识符。TCP初次连接
FIN:结束表示。TCP断开连接
- 16位窗口大小:它记录的是接收缓冲区窗口的大小,这个是动态改变的
(不等于滑动窗口的大小,因为滑动窗口的大小是固定不变的,所以不需要传)
- 16位校验和: 用来确定当前数据是否是正确的
- 16位紧急指针: 标识哪部分数据是紧急数据;
- 40字节头部选项: 暂时忽略
2.3.1 TCP1大核心和8大特性
特性1:确认应答(核心机制)
保障TCP稳定的核心机制
每一个ACK都带有对应的确认序列号, 意思是告诉发送者, 我已经收到了哪些数据; 下一次你从哪里开始发
特性2:超时重传
为解决确认应答的非正常情况
对于发送重复消息的问题,不用担心,因为系统(内核)帮程序去做去重操作
TCP稳定的核心就是:确认应答+超时重传
超时重发策略1:使用递增时间段来发送
超时重发策略2:尝试多次发送失败后停止发送
当进经过了一定次数的发送后,还是没有结果,那么发送端就会认为接收端下线了
特性3:连接管理
连接:3次握手
断开连接:4次挥手
3次握手:
TCP特性:有连接
有连接必须要证明4个:
- 发送方的发送能力(话筒)
- 发送方的接收能力(耳机)
- 接收方的发送能力(对方话筒)
- 接收方的接收能力(对方的耳机)
4次挥手:
TCP有发送缓冲区和接收缓冲区,所以
- 如果缓冲区里有数据,就得把数据处理完走
- 若没有缓冲区没有数据,直接就走
3次挥手行不行?
有可能可以,23步有可能会合并(如果接收端没有要处理东西的话)
CLOSE_WAIT -> 如果发现服务器端存在大量的CLOSE_WAIT说明程序有什么问题?
程序有BUG,程序中没有调用close()主导那个关闭连接
TIME_WAIT -> CLOSE 要经历两个MSL(最大生存时间)?
2MSL = ACK最大超时连接(1MSL) + 对方发给他消息的一个最大等待时间(1MSL)
(1)等ACK
(2)失败后,再发一个消息,再等重发的FIN
特性4:滑动窗口
目的:保证传输的性能
情况一:数据包已经抵达, ACK被丢了
当返回ack=6001说明服务器已经接收到了1-6000的数据了
ack返回的是接收缓冲区的最大值
如果最前面和最后面的丢了,那么服务器就会再发一遍,然后进行对比
情况二: 数据包就直接丢了
快速重传:
当前面的数据被正常补齐之后,返回ACK是最大值,这种机制叫作快重传
特性五:流量控制
接收端处理数据的速度是有限的. 如果发送端发的太快, 导致接收端的缓冲区被打满, 这个时候如果发送端继续发送, 就会造成丢包, 继而引起丢包重传等等一系列连锁反应
根据接收端的处理能力, 来决定发送端的发送速度. 这个机制就叫做流量控制
如果TCP协议头的16位窗口的大小位0,表示接收缓冲区已经满了,不能再发了。此时发送端就不会进行消息的发送了,发送端会定时发送一个探测包,用来检测接收缓冲区的大小,如果接收缓冲区有值了,那么消息就可以继续发送了
总结:以结果(接收缓冲区的大小)为导向进行数据的传递
特性六:拥塞控制
和你当前的网络有关
以当前时间的网络来动态调整收发的频率就叫拥塞控制
规则:
发包从1开始,以默认值16为临界值,当小于此值的时候,以指数增加的方式发包,当等于这个此值就有线性增长的方式发包,一直到有大量丢包的请求(发包已经到当前时间段的极致);这个时候就会:
(1)将发包值置为1
(2)再将临界值设置为最大发包值的一半
继续重复此过程,一直循环此过程
整个过程就叫慢开始
- 当TCP开始启动的时候, 慢启动阈值等于窗口最大值;
- 在每次超时重发的时候, 慢启动阈值会变成原来的一半, 同时拥塞窗口置回1;
总结:以当前网络环境的拥塞程度为导向
特性七:延迟应答
延迟应答是在流量控制的基础上进行优化发送效率
TCP:
策略一:固定一定时间段,发送一个延迟应答包
策略二:接收一定次数的包之后,来一个延迟应答
注意事项:延迟应答时间不能超过MSL(最大生存时间)
如果超过MSL就会触发超时重传,它会以为消息丢失
特性八:捎带应答
是在延迟应答的基础上继续又转换传输效率
在延迟应答的基础上, 我们发现, 很多情况下, 客户端服务器在应用层也是 “一发一收” 的. 意味着客户端给
服务器说了 “How are you”, 服务器也会给客户端回一个 “Fine, thank you”;
那么这个时候ACK就可以搭顺风车, 和服务器回应的 “Fine, thank you” 一起回给客户端
捎带应答是针对延迟应答所进行的性能优化
2.3.2 粘包问题
- 首先要明确, 粘包问题中的 “包” , 是指的应用层的数据包.
- 在TCP的协议头中, 没有如同UDP一样的 “报文长度” 这样的字段, 但是有一个序号这样的字段.
- 站在传输层的角度, TCP是一个一个报文过来的. 按照序号排好序放在缓冲区中.
- 站在应用层的角度, 看到的只是一串连续的字节数据.
- 那么应用程序看到了这么一连串的字节数据, 就不知道从哪个部分开始到哪个部分, 是一个完 整的应用层数据包
那么如何避免粘包问题呢?
归根结底就是一句话, 明确两个包之间的边界
- 对于定长的包, 保证每次都按固定大小读取即可; 例如上面的Request结构, 是固定大小的, 那
么就从缓冲区从头开始按sizeof(Request)依次读取即可;
- 对于变长的包, 可以在包头的位置, 约定一个包总长度的字段, 从而就知道了包的结束位置;
- 对于变长的包, 还可以在包和包之间使用明确的分隔符(应用层协议, 是程序猿自己来定的, 只 要保证分隔符不和正文冲突即可);
具体方法:
- 使用/n作为流的结束符,这样流就有边界了,就能正常收发消息了
- 每次发固定大小的流信息,这样也能确定每个数据流的边界,也就能正常的收发消息了
对于UDP协议来说, 是否也存在 “粘包问题” 呢?
-
对于UDP, 如果还没有上层交付数据, UDP的报文长度仍然在. 同时, UDP是一个一个把数据交 付给应用层. 就有很明确的数据边界.
-
站在应用层的站在应用层的角度, 使用UDP的时候, 要么收到完整的UDP报文, 要么不收. 不会 出现"半个"的情况
2.3.3 TCP异常情况
- 进程终止: 进程终止会释放文件描述符, 仍然可以发送FIN. 和正常关闭没有什么区别.
- 机器重启: 和进程终止的情况相同.
- 机器掉电/网线断开: 接收端认为连接还在, 一旦接收端有写入操作, 接收端发现连接已经不在了, 就会进行 reset. 即使没有写入操作,TCP自己也内置了一个保活定时器, 会定期询问对方是否还在. 如果对方不在, 也会把连接释放.
- 另外, 应用层的某些协议, 也有一些这样的检测机制. 例如HTTP长连接中, 也会定期检测对方的状态. 例如 QQ, 在QQ断线之后,也会定期尝试重新连接
2.3.4 基于TCP应用层协议
- HTTP:简单的请求-响应协议
- HTTPS:以安全为目标的 HTTP 通道
- SSH:安全外壳协议
- Telnet:Internet远程登录服务的标准协议
- FTP:文件传输协议
- SMTP:电子邮件传输的协议
2.3.5 小结TCP
可靠性:
- 校验和
- 序列号(按序到达)
- 确认应答
- 超时重发
- 连接管理
- 流量控制
- 拥塞控制
提高性能:
其他:
- 定时器(超时重传定时器, 保活定时器, TIME_WAIT定时器等)
2.4TCP/UDP对比
- UDP是无连接的;TCP是有连接的
- UDP是不稳定的;TCP是稳定的
- UDP是面向数据报的;TCP是面向数据流的
- UDP没有发送缓冲区;TCP有发送缓冲区
- UDP是以高效性著称;TCP是以稳定性著称
- 使用的场景不同
如果对稳定性要求比较高,那么应该使用TCP
如果对消息丢失不敏感,要求性能比较高,那么可以考虑使用UDP
如何使用UDP实现稳定的消息传输?
参考TCP实现稳定性的特性来设计UDP
3 网络层
3.1 IP协议
3.1.1 头格式
- 4位版本号(version): 指定IP协议的版本, 对于IPv4来说, 就是4
- 4位头部长度(header length): IP头部的长度是多少个32bit, 也就是 length * 4 的字节数. 4bit表示最大的数字是15, 因此IP头部最大长度是60字节
- 8位服务类型:3位优先权字段(已经弃用), 4位TOS字段, 和1位保留字段(必须置为0). 4位TOS分别表示: 最小延时, 最大吞吐量, 最高可靠性, 最小成本. 这四者相互冲突, 只能选择一个. 对于ssh/telnet这样的应用程序, 最小延时比较重要; 对于ftp这样的程序, 最大吞吐量比较重要
- 16位总长度(total length): IP数据报整体占多少个字节
- 3位标志字段: 第一位保留,第二位置为1表示禁止分片,第三位表示"更多分片"
- 13位分片偏移:确定组包时的顺序
- 8位生存时间SSL:一般为64,每经过路由器的跳转这个值-1,直到这个值等于0,表示是个无效的地址,直接舍弃。
- 16位头部校验和:验证首部是否正确
- 32位源地址和32位目标地址: 表示发送端和接收端
3.1.2 网络划分
IP地址分为两个部分, 网络号和主机号
网络号: 保证相互连接的两个网段具有不同的标识;
主机号: 同一网段内, 主机之间具有相同的网络号, 但是必须有不同的主机号;
A类 0.0.0.0到127.255.255.255
B类 128.0.0.0到191.255.255.255
C类 192.0.0.0到223.255.255.255
D类 224.0.0.0到239.255.255.255
E类 240.0.0.0到247.255.255.255
网络号:IP地址和子网掩码按位与
例子1:
子网掩码最后一位为0,到255有 255个
子网号最后一位从0,到0+255 = 255
例子2:
子网掩码最后一位为240,到255有 15 个
子网号最后一位从64,到64+15 = 79
3.1.3 私网IP地址
如果一个组织内部组建局域网,IP地址只用于局域网内的通信,而不直接连到Internet上,理论上 使用任意
的IP地址都可以,但是RFC 1918规定了用于组建局域网的私有IP地址
- 10.*,前8位是网络号,共16,777,216个地址
- 172.16.到172.31.,前12位是网络号,共1,048,576个地址
- 192.168.*,前16位是网络号,共65,536个地址
包含在这个范围中的, 都成为私有IP, 其余的则称为全局IP(或公网IP);
3.1.4 路由
过程:
- 当IP数据包, 到达路由器时, 路由器会先查看目的IP;
- 路由器决定这个数据包是能直接发送给目标主机, 还是需要发送给下一个路由器;
- 依次反复, 一直到达目标IP地址;
4 数据链路层
4.1 以太网
“以太网” 不是一种具体的网络, 而是一种技术标准; 既包含了数据链路层的内容, 也包含了一些
物理层的内容. 例如: 规定了网络拓扑结构, 访问控制方式, 传输速率等;
4.1.1 以太网帧格式
- 源地址和目的地址是指网卡的硬件地址(也叫MAC地址), 长度是48位,是在网卡出厂时固化的;
- 帧协议类型字段有三种值,分别对应IP、ARP、RARP;
- 帧末尾是CRC校验码:用来效验数据的正确性
4.2 MAC地址和IP地址
- IP地址描述的是路途总体的 起点 和 终点;
- MAC地址描述的是路途上的每一个区间的起点和终点
4.3 MTU
大传输单元,MTU相当于发快递时对包裹尺寸的限制. 这个限制是不同的数据链路对应的物理层, 产生的限制
MTU 对 UDP 的影响:
1500 - UDP(固定头部信息)8字节 - IP协议头部20字节 = 1472 字节
MTU对于TCP协议的影响:
TCP的一个数据报也不能无限大, 还是受制于MTU. TCP的单个数据报的最大消息长度, 称为
MSS(Max Segment Size);
TCP在建立连接的过程中, 通信双方会进行MSS协商。
MTU = IP Header + TCP Header + DAT(MSS)
4.4 ARP协议
定义
ARP不是一个单纯的数据链路层的协议, 而是一个介于数据链路层和网络层之间的协议
作用:
ARP协议建立了主机 IP地址 和 MAC地址 的映射关系
工作方式:
- 源主机发出ARP请求在网络中寻找IP地址
- 目的主机收到请求并返回ARP应答数据包给源主机
- 此时源地址和目标地址已经找到,构建完成MAC地址,相应的以太帧也完成
5 物理层
以0,1代表电压的高低,灯光的闪灭,界定连接器和网络的规格
相当于一些基站,电信号和光信号
6 补充重点
6.1 DNS
TCP/IP中使用IP地址和端口号来确定网络上的一台主机的一个程序. 但是IP地址不方便记忆.
端口号:53
于是人们发明了一种叫主机名的东西, 是一个字符串, 并且使用hosts文件来描述主机名和IP地址的关系.
6.2 浏览器中输入url后, 发生的事情
- 浏览器会先检查你的url地址的正确性
- 浏览器会检查这个url有没有缓存,如果有缓存就取缓存
- DNS域名解析,拿到IP进行访问
- TCP 3次握手(TCP握手的内容传递和状态变化)
- HTTP 协议 Resquest 内容发送 (首行,head,空行,body)
- 服务器接收到请求,并且进行相应的业务处理
- 服务器端将结果返回给客户端
- 浏览器拿到返回的结果并调用浏览器的内核,实现前端页面的渲染
- TCP 的4次挥手
6.3 NAT技术
目的:解决 IP 不足的问题
本质:实现一个映射,内网 IP 到外网 IP 的映射
NAT缺点:
- 部署和运行 NAT 服务是需要硬件支持的
- 当 NAT 挂掉之后,整个局域网就瘫痪了
NAT vs 代理
- 应用场景:NAT 是解决 IP 不足的问题;代理是解决网络不能到达的问题
- 部署:NAT 通常会部署在防火墙;代理是一个软件,直接安装使用
- 所在层级:NAT 是网络层的;代理是应用层。