起源:https://juejin.im/post/684490…
作者:Ruheng
本文整顿了一些 TCP/IP 协定簇中须要必知必会的十大问题,既是面试高频问题,又是程序员必备根底素养。
TCP/IP 十个问题
一、TCP/IP 模型
TCP/IP 协定模型(Transmission Control Protocol/Internet
Protocol),蕴含了一系列形成互联网根底的网络协议,是 Internet 的外围协定。
基于 TCP/IP 的参考模型将协定分成四个档次,它们别离是链路层、网络层、传输层和应用层。下图示意 TCP/IP 模型与 OSI 模型各层的对照关系。
TCP/IP 协定族依照档次由上到下,层层包装。最下面的是应用层,这外面有 http,ftp, 等等咱们相熟的协定。而第二层则是传输层,驰名的 TCP 和 UDP 协定就在这个档次。第三层是网络层,IP 协定就在这里,它负责对数据加上 IP 地址和其余的数据以确定传输的指标。第四层是数据链路层,这个档次为待传送的数据退出一个以太网协定头,并进行 CRC 编码,为最初的数据传输做筹备。
上图分明地示意了 TCP/IP 协定中每个层的作用,而 TCP/IP 协定通信的过程其实就对应着数据入栈与出栈的过程。入栈的过程,数据发送方每层一直地封装首部与尾部,增加一些传输的信息,确保能传输到目的地。出栈的过程,数据接管方每层一直地拆除首部与尾部,失去最终传输的数据。
上图以 HTTP 协定为例,具体阐明。
二、数据链路层
物理层负责 0、1 比特流与物理设施电压高下、光的闪灭之间的调换。
数据链路层负责将 0、1 序列划分为数据帧从一个节点传输到邻近的另一个节点, 这些节点是通过 MAC 来惟一标识的(MAC, 物理地址,一个主机会有一个 MAC 地址)。
- 封装成帧: 把网络层数据报加头和尾,封装成帧, 帧头中包含源 MAC 地址和目标 MAC 地址。
- 通明传输: 零比特填充、转义字符。
- 牢靠传输: 在出错率很低的链路上很少用,然而无线链路 WLAN 会保障牢靠传输。
- 过错检测(CRC): 接收者检测谬误, 如果发现过错,抛弃该帧。
三、网络层
1.IP 协定
IP 协定是 TCP/IP 协定的外围,所有的 TCP,UDP,IMCP,IGMP 的数据都以 IP 数据格式传输。要留神的是,IP 不是牢靠的协定,这是说,IP 协定没有提供一种数据未传播当前的解决机制,这被认为是下层协定:TCP 或 UDP 要做的事件。
1.1 IP 地址
在数据链路层中咱们个别通过 MAC 地址来辨认不同的节点,而在 IP 层咱们也要有一个相似的地址标识,这就是 IP 地址。
32 位 IP 地址分为网络位和地址位,这样做能够缩小路由器中路由表记录的数目,有了网络地址,就能够限定领有雷同网络地址的终端都在同一个范畴内,那么路由表只须要保护一条这个网络地址的方向,就能够找到相应的这些终端了。
A 类 IP 地址: 0.0.0.0~127.0.0.0
B 类 IP 地址:128.0.0.1~191.255.0.0
C 类 IP 地址:192.168.0.0~239.255.255.0
1.2 IP 协定头
这里只介绍: 八位的 TTL 字段。这个字段规定该数据包在穿过多少个路由之后才会被摈弃。某个 IP 数据包每穿过一个路由器,该数据包的 TTL 数值就会缩小 1,当该数据包的 TTL 成为零,它就会被主动摈弃。
这个字段的最大值也就是 255,也就是说一个协定包也就在路由器外面穿行 255 次就会被抛弃了,依据零碎的不同,这个数字也不一样,个别是 32 或者是 64。
2.ARP 及 RARP 协定
ARP 是依据 IP 地址获取 MAC 地址的一种协定。
ARP(地址解析)协定是一种解析协定,原本主机是齐全不晓得这个 IP 对应的是哪个主机的哪个接口,当主机要发送一个 IP 包的时候,会首先查一下本人的 ARP 高速缓存(就是一个 IP-
MAC 地址对应表缓存)。
如果查问的 IP-MAC 值对不存在,那么主机就向网络发送一个 ARP 协定播送包,这个播送包外面就有待查问的 IP 地址,而间接收到这份播送的包的所有主机都会查问本人的 IP 地址,如果收到播送包的某一个主机发现自己符合条件,那么就筹备好一个蕴含本人的 MAC 地址的 ARP 包传送给发送 ARP 播送的主机。
而播送主机拿到 ARP 包后会更新本人的 ARP 缓存(就是寄存 IP-
MAC 对应表的中央)。发送播送的主机就会用新的 ARP 缓存数据筹备好数据链路层的的数据包发送工作。
RARP 协定的工作与此相反,不做赘述。
3\. ICMP 协定
IP 协定并不是一个牢靠的协定,它不保证数据被送达,那么,天然的,保证数据送达的工作应该由其余的模块来实现。其中一个重要的模块就是 ICMP(网络管制报文)协定。ICMP 不是高层协定,而是 IP 层的协定。
当传送 IP 数据包产生谬误。比方主机不可达,路由不可达等等,ICMP 协定将会把错误信息封包,而后传送回给主机。给主机一个处理错误的机会,这
也就是为什么说建设在 IP 层以上的协定是可能做到平安的起因。
四、ping
ping 能够说是 ICMP 的最驰名的利用,是 TCP/IP 协定的一部分。利用“ping”命令能够查看网络是否连通,能够很好地帮忙咱们剖析和断定网络故障。
例如:当咱们某一个网站上不去的时候。通常会 ping 一下这个网站。ping 会回显出一些有用的信息。个别的信息如下:
ping 这个单词源自声纳定位,而这个程序的作用也的确如此,它利用 ICMP 协定包来侦测另一个主机是否可达。原理是用类型码为 0 的 ICMP 发请
求,受到申请的主机则用类型码为 8 的 ICMP 回应。
ping 程序来计算间隔时间,并计算有多少个包被送达。用户就能够判断网络大抵的状况。咱们能够看到,ping 给进去了传送的工夫和 TTL 的数据。
五、Traceroute
Traceroute 是用来侦测主机到目标主机之间所经路由状况的重要工具,也是最便当的工具。
Traceroute 的原理是十分十分的有意思,它收到到目标主机的 IP 后,首先给目标主机发送一个 TTL= 1 的 UDP 数据包,而通过的第一个路由器收到这个数据包当前,就主动把 TTL 减 1,而 TTL 变为 0 当前,路由器就把这个包给摈弃了,并同时产生
一个主机不可达的 ICMP 数据报给主机。主机收到这个数据报当前再发一个 TTL= 2 的 UDP 数据报给目标主机,而后刺激第二个路由器给主机发 ICMP 数据
报。如此往返直到达到目标主机。这样,traceroute 就拿到了所有的路由器 IP。
六、TCP/UDP
TCP/UDP 都是是传输层协定,然而两者具备不同的个性,同时也具备不同的利用场景,上面以图表的模式比照剖析。
面向报文
面向报文的传输方式是应用层交给 UDP 多长的报文,UDP 就照样发送,即一次发送一个报文。因而,应用程序必须抉择适合大小的报文。若报文太长,则 IP 层须要分片,升高效率。若太短,会是 IP 太小。
面向字节流
面向字节流的话,尽管应用程序和 TCP 的交互是一次一个数据块(大小不等),但 TCP 把应用程序看成是一连串的无构造的字节流。TCP 有一个缓冲,当应用程序传送的数据块太长,TCP 就能够把它划分短一些再传送。
对于拥塞管制,流量管制,是 TCP 的重点,前面解说。
TCP 和 UDP 协定的一些利用
什么时候应该应用 TCP?
当对网络通讯品质有要求的时候,比方:整个数据要准确无误的传递给对方,这往往用于一些要求牢靠的利用,比方 HTTP、HTTPS、FTP 等传输文件的协定,POP、SMTP 等邮件传输的协定。
什么时候应该应用 UDP?
当对网络通讯品质要求不高的时候,要求网络通讯速度能尽量的快,这时就能够应用 UDP。
七、DNS
DNS(Domain Name
System,域名零碎),因特网上作为域名和 IP 地址互相映射的一个分布式数据库,可能使用户更不便的拜访互联网,而不必去记住可能被机器间接读取的 IP 数串。通过主机名,最终失去该主机名对应的 IP 地址的过程叫做域名解析(或主机名解析)。DNS 协定运行在 UDP 协定之上,应用端口号 53。
八、TCP 连贯的建设与终止
1. 三次握手
TCP 是面向连贯的,无论哪一方向另一方发送数据之前,都必须先在单方之间建设一条连贯。在 TCP/IP 协定中,TCP 协定提供牢靠的连贯服务,连贯是通过三次握手进行初始化的。三次握手的目标是同步连贯单方的序列号和确认号并替换
TCP 窗口大小信息。
第一次握手: 建设连贯。客户端发送连贯申请报文段,将 SYN 地位为 1,Sequence
Number 为 x;而后,客户端进入 SYN_SEND 状态,期待服务器的确认;
第二次握手: 服务器收到 SYN 报文段。服务器收到客户端的 SYN 报文段,须要对这个 SYN 报文段进行确认,设置 Acknowledgment Number 为 x +1(Sequence Number+1);同时,本人本人还要发送 SYN 申请信息,将 SYN 地位为 1,Sequence
Number 为 y;服务器端将上述所有信息放到一个报文段(即 SYN+ACK 报文段)中,一并发送给客户端,此时服务器进入 SYN_RECV 状态;
第三次握手: 客户端收到服务器的 SYN+ACK 报文段。而后将 Acknowledgment
Number 设置为 y +1,向服务器发送 ACK 报文段,这个报文段发送结束当前,客户端和服务器端都进入 ESTABLISHED 状态,实现 TCP 三次握手。
为什么要三次握手?
为了避免已生效的连贯申请报文段忽然又传送到了服务端,因此产生谬误。
具体例子:“已生效的连贯申请报文段”的产生在这样一种状况下:client 收回的第一个连贯申请报文段并没有失落,而是在某个网络结点长时间的滞留了,以至延误到连贯开释当前的某个工夫才达到 server。原本这是一个早已生效的报文段。但 server 收到此生效的连贯申请报文段后,就误认为是 client 再次收回的一个新的连贯申请。于是就向 client 收回确认报文段,批准建设连贯。假如不采纳“三次握手”,那么只有 server 收回确认,新的连贯就建设了。因为当初 client 并没有收回建设连贯的申请,因而不会理会 server 的确认,也不会向 server 发送数据。但 server 却认为新的运输连贯曾经建设,并始终期待 client 发来数据。这样,server 的很多资源就白白浪费掉了。采纳“三次握手”的方法能够避免上述景象产生。例如方才那种状况,client 不会向 server 的确认收回确认。server 因为收不到确认,就晓得 client 并没有要求建设连贯。”
2. 四次挥手
当客户端和服务器通过三次握手建设了 TCP 连贯当前,当数据传送结束,必定是要断开 TCP 连贯的啊。那对于 TCP 的断开连接,这里就有了神秘的“四次离别”。
第一次离别: 主机 1(能够使客户端,也能够是服务器端),设置 Sequence
Number,向主机 2 发送一个 FIN 报文段;此时,主机 1 进入 FIN_WAIT_1 状态;这示意主机 1 没有数据要发送给主机 2 了;
第二次离别: 主机 2 收到了主机 1 发送的 FIN 报文段,向主机 1 回一个 ACK 报文段,Acknowledgment Number 为 Sequence Number 加 1;主机 1 进入 FIN_WAIT_2 状态;主机 2 通知主机 1,我“批准”你的敞开申请;
第三次离别: 主机 2 向主机 1 发送 FIN 报文段,申请敞开连贯,同时主机 2 进入 LAST_ACK 状态;
第四次离别: 主机 1 收到主机 2 发送的 FIN 报文段,向主机 2 发送 ACK 报文段,而后主机 1 进入 TIME_WAIT 状态;主机 2 收到主机 1 的 ACK 报文段当前,就敞开连贯;此时,主机 1 期待 2MSL 后仍然没有收到回复,则证实 Server 端已失常敞开,那好,主机 1 也能够敞开连贯了。
为什么要四次离别?
TCP 协定是一种面向连贯的、牢靠的、基于字节流的运输层通信协议。TCP 是全双工模式,这就意味着,当主机 1 收回 FIN 报文段时,只是示意主机 1 曾经没有数据要发送了,主机 1 通知主机 2,它的数据曾经全副发送结束了;然而,这个时候主机 1 还是能够承受来自主机 2 的数据;当主机 2 返回 ACK 报文段时,示意它曾经晓得主机 1 没有数据发送了,然而主机 2 还是能够发送数据到主机 1 的;当主机 2 也发送了 FIN 报文段时,这个时候就示意主机 2 也没有数据要发送了,就会通知主机 1,我也没有数据要发送了,之后彼此就会欢快的中断这次 TCP 连贯。
为什么要期待 2MSL?
MSL:报文段最大生存工夫,它是任何报文段被抛弃前在网络内的最长工夫。
起因有二:
- 保障 TCP 协定的全双工连贯可能牢靠敞开
- 保障这次连贯的反复数据段从网络中隐没
第一点:如果主机 1 间接 CLOSED 了,那么因为 IP 协定的不可靠性或者是其它网络起因,导致主机 2 没有收到主机 1 最初回复的 ACK。那么主机 2 就会在超时之后持续发送 FIN,此时因为主机 1 曾经 CLOSED 了,就找不到与重发的 FIN 对应的连贯。所以,主机 1 不是间接进入 CLOSED,而是要放弃 TIME_WAIT,当再次收到 FIN 的时候,可能保障对方收到 ACK,最初正确的敞开连贯。
第二点:如果主机 1 间接 CLOSED,而后又再向主机 2 发动一个新连贯,咱们不能保障这个新连贯与刚敞开的连贯的端口号是不同的。也就是说有可能新连贯和老连贯的端口号是雷同的。一般来说不会产生什么问题,然而还是有非凡状况呈现:假如新连贯和曾经敞开的老连贯端口号是一样的,如果前一次连贯的某些数据依然滞留在网络中,这些提早数据在建设新连贯之后才达到主机 2,因为新连贯和老连贯的端口号是一样的,TCP 协定就认为那个提早的数据是属于新连贯的,这样就和真正的新连贯的数据包产生混同了。所以 TCP 连贯还要在 TIME_WAIT 状态期待 2 倍 MSL,这样能够保障本次连贯的所有数据都从网络中隐没。
九、TCP 流量管制
如果发送方把数据发送得过快,接管方可能会来不及接管,这就会造成数据的失落。所谓 流量管制 就是让发送方的发送速率不要太快,要让接管方来得及接管。
利用 滑动窗口机制 能够很不便地在 TCP 连贯上实现对发送方的流量管制。
设 A 向 B 发送数据。在连贯建设时,B 通知了 A:“我的接管窗口是 rwnd = 400”(这里的 rwnd 示意 receiver window)
。因而,发送方的发送窗口不能超过接管方给出的接管窗口的数值。请留神,TCP 的窗口单位是字节,不是报文段。假如每一个报文段为 100 字节长,而数据报文段序号的初始值设为 1。大写 ACK 示意首部中的确认位 ACK,小写 ack 示意确认字段的值 ack。
从图中能够看出,B 进行了三次流量管制。第一次把窗口缩小到 rwnd = 300,第二次又减到了 rwnd = 100,最初减到 rwnd = 0
,即不容许发送方再发送数据了。这种使发送方暂停发送的状态将继续到主机 B 从新收回一个新的窗口值为止。B 向 A 发送的三个报文段都设置了 ACK = 1
,只有在 ACK= 1 时确认号字段才有意义。
TCP 为每一个连贯设有一个继续计时器(persistence
timer)。只有 TCP 连贯的一方收到对方的零窗口告诉,就启动继续计时器。若继续计时器设置的工夫到期,就发送一个零窗口控测报文段(携 1 字节的数据),那么收到这个报文段的一方就从新设置继续计时器。
十、TCP 拥塞管制
1. 慢开始和拥塞防止
发送方维持一个拥塞窗口 cwnd (congestion window
)的状态变量。拥塞窗口的大小取决于网络的拥塞水平,并且动静地在变动。发送方让本人的发送窗口等于拥塞窗口。
发送方管制拥塞窗口的准则是:只有网络没有呈现拥塞,拥塞窗口就再增大一些,以便把更多的分组发送进来。但只有网络呈现拥塞,拥塞窗口就减小一些,以缩小注入到网络中的分组数。
慢开始算法:
当主机开始发送数据时,如果立刻所大量数据字节注入到网络,那么就有可能引起网络拥塞,因为当初并不分明网络的负荷状况。
因而,较好的办法是 先探测一下,即由小到大逐步增大发送窗口,也就是说,由小到大逐步增大拥塞窗口数值。
通常在刚刚开始发送报文段时,先把拥塞窗口 cwnd
设置为一个最大报文段 MSS 的数值。而在每收到一个对新的报文段的确认后,把拥塞窗口减少至少一个 MSS 的数值。用这样的办法逐渐增大发送方的拥塞窗口 cwnd
,能够使分组注入到网络的速率更加正当。
每通过一个传输轮次,拥塞窗口 cwnd 就加倍。一个传输轮次所经验的工夫其实就是往返工夫 RTT。
不过“传输轮次”更加强调:把拥塞窗口 cwnd 所容许发送的报文段都间断发送进来,并收到了对已发送的最初一个字节的确认。
另,慢开始的“慢”并不是指 cwnd 的增长速率慢,而是指在 TCP 开始发送报文段时先设置 cwnd=1,使得发送方在开始时只发送一个报文段(目标是试探一下网络的拥塞状况),而后再逐步增大 cwnd。
为了避免拥塞窗口 cwnd 增长过大引起网络拥塞,还须要设置一个慢开始门限 ssthresh 状态变量。慢开始门限 ssthresh 的用法如下:
- 当 cwnd < ssthresh 时,应用上述的慢开始算法。
- 当 cwnd > ssthresh 时,停止使用慢开始算法而改用拥塞防止算法。
- 当 cwnd = ssthresh 时,既可应用慢开始算法,也可应用拥塞管制防止算法。
拥塞防止
让拥塞窗口 cwnd 迟缓地增大,即每通过 一个往返工夫 RTT 就把发送方的 拥塞窗口 cwnd 加 1,而不是加倍
。这样拥塞窗口 cwnd 按线性法则迟缓增长,比慢开始算法的拥塞窗口增长速率迟缓得多。
无论在慢开始阶段还是在拥塞防止阶段,只有发送方判断网络呈现拥塞(其依据就是没有收到确认),就要把慢开始门限 ssthresh 设置为呈现拥塞时的发送
方窗口值的一半(但不能小于 2)。而后把拥塞窗口 cwnd 从新设置为 1,执行慢开始算法。
这样做的目标就是要迅速缩小主机发送到网络中的分组数,使得产生 拥塞的路由器有足够工夫把队列中积压的分组处理完毕。
如下图,用具体数值阐明了上述拥塞管制的过程。当初发送窗口的大小和拥塞窗口一样大。
2. 快重传和快复原
快重传
快重传算法首先要求接管方每收到一个失序的报文段后就立刻收回反复确认(为的是使发送方及早晓得有报文段没有达到对方)而不要等到本人发送数据时才进行捎带确认。
接管方收到了 M1 和 M2 后都别离收回了确认。当初假设接管方没有收到 M3 但接着收到了 M4。
显然,接管方不能确认 M4,因为 M4 是收到的失序报文段。依据 牢靠传输原理,接管方能够什么都不做,也能够在适当机会发送一次对 M2 的确认。
但依照快重传算法的规定,接管方应及时发送对 M2 的反复确认,这样做能够让
发送方及早晓得报文段 M3 没有达到接管方。发送方接着发送了 M5 和 M6。接管方收到这两个报文后,也还要再次收回对 M2 的反复确认。这样,发送方共收到了
接管方的四个对 M2 的确认,其中后三个都是反复确认。
快重传算法还规定,发送方只有一连收到三个反复确认就该当立刻重传对方尚未收到的报文段 M3,而不用 持续期待 M3 设置的重传计时器到期。
因为发送方尽早重传未被确认的报文段,因而采纳快重传后能够使整个网络吞吐量进步约 20%。
快复原
与快重传配合应用的还有快复原算法,其过程有以下两个要点:
- 当发送方间断收到三个反复确认,就执行“乘法减小”算法,把慢开始门限 ssthresh 减半。
- 与慢开始不同之处是当初不执行慢开始算法(即拥塞窗口 cwnd 当初不设置为 1),而是把 cwnd 值设置为 慢开始门限 ssthresh 减半后的数值,而后开始执行拥塞防止算法(“加法增大”),使拥塞窗口迟缓地线性增大。
参考援用
- TCP 三次握手、四手挥手,这样说你能明确吧!
- TCP/IP 教程