引言
最近读完两本不错的书,一本是《现代操作系统:原理与实现》。
这本书很详细的阐述了OS方面的知识,有的术语很新,也比较晦涩难懂。
建议看的时候可以不用太在意细节,一些记了肯定忘的英文缩写之类的理解其思想就好,抓重点学习。
这本书的配套lab我没有做,但是听说不错,感兴趣的同学可以做做。由于是纸质书不方便做笔记,我就只简单的在纸上记了一些关键词来帮助我复习,故不放上来。
另一本是面向就业的图解教程,由小林coding这个良心博主总结。
这本书写的很通俗易懂,对于一些点钻研的也很深,不过内容覆盖面不是特别广,个人觉得适合初学者和突击就业的人阅读。
图解系统那本我也看了一些,过段时间看完了同样放上来,不过最近有些别的事。
大家可以直接在微信公众号搜索小林coding去获取这本书。
一、基础篇
- 应⽤层是⼯作在操作系统中的⽤户态,传输层及以下则⼯作在内核态。
- UDP也可以实现可靠传输,把TCP的特性在应⽤层上实现就可以。
- 当传输层的数据包⼤⼩超过MSS(TCP最⼤报⽂段⻓度),就要将数据包分块。
- 在TCP协议中,我们把每个分块称为⼀个TCP段(TCPSegment)。
二、HTTP篇
-
超⽂本是超越了普通⽂本的⽂本,它是⽂字、图⽚、视频等的混合体,最关键有超链接,能从⼀个超⽂本跳转到另外⼀个超⽂本。
-
Get⽅法的含义是请求从服务器获取资源,这个资源可以是静态的⽂本、⻚⾯、图⽚视频等。⽽POST⽅法则是相反操作,它向URI指定的资源提交数据,数据就放在报⽂的body⾥。GET⽅法就是安全且幂等的,POST方法不是。
-
HTTPS就是在HTTP与TCP层之间增加了SSL/TLS安全传输层。
-
HTTP连接建⽴相对简单,TCP三次握⼿之后便可进⾏HTTP的报⽂传输。⽽HTTPS在TCP三次握⼿之后,还需进⾏SSL/TLS的握⼿过程,才可进⼊加密报⽂传输。
-
HTTPS协议需要向CA(证书权威机构)申请数字证书,来保证服务器的身份是可信的。
-
HTTPS:
-
混合加密:
- HTTPS采⽤的是对称加密和⾮对称加密结合的「混合加密」⽅式:
- 在通信建⽴前采⽤⾮对称加密的⽅式交换「会话秘钥」,后续就不再使⽤⾮对称加密。
- 在通信过程中全部使⽤对称加密的「会话秘钥」的⽅式加密明⽂数据。
- 采⽤「混合加密」的⽅式的原因:
对称加密只使⽤⼀个密钥,运算速度快,密钥必须保密,⽆法做到安全的密钥交换。 - ⾮对称加密使⽤两个密钥:
- 公钥和私钥,公钥可以任意分发⽽私钥保密,解决了密钥交换问题但速度慢。
- 因为考虑到性能的问题,所以双⽅在加密应⽤信息时使⽤的是对称加密密钥,⽽对称加密密钥是不能被泄漏的,为了保证对称加密密钥的安全性,所以使⽤⾮对称加密的⽅式来保护对称加密密钥的协商,这个⼯作就是密钥交换算法负责的。
-
摘要算法:
摘要算法⽤来实现完整性,能够为数据⽣成独⼀⽆⼆的「指纹」,⽤于校验数据的完整性,解决了篡改的⻛险。
-
数字证书:
借助第三⽅权威机构CA(数字证书认证机构),将服务器公钥放在数字证书(由数字证书认证机构颁发)中,只要证书是可信的,公钥就是可信的。CA的公钥已事先置入到了浏览器或操作系统中。
-
-
私钥加密算法,又称对称加密算法。公钥加密算法,也就是非对称加密算法。
公钥和私钥成对出现,公开的密钥叫公钥,只有自己知道的叫私钥,用公钥加密的数据只有对应的私钥可以解密,用私钥加密的数据只有对应的公钥可以解密。
-
HTTP/2:
-
头部压缩在客户端和服务器同时维护⼀张头信息表,所有字段都会存⼊这个表,⽣成⼀个索引号,以后就不发送同样字段了,只发送索引号。
-
⼆进制格式HTTP/2不再像HTTP/1.1⾥的纯⽂本形式的报⽂,⽽是全⾯采⽤了⼆进制格式,头信息和数据体都是⼆进制,并且统称为帧(frame):头信息帧和数据帧。
-
数据流:
每个请求或回应的所有数据包,称为⼀个数据流(Stream)。每个数据流都标记着⼀个独⼀⽆⼆的编号,其中规
定客户端发出的数据流编号为奇数,服务器发出的数据流编号为偶数。 -
多路复⽤:
HTTP/2是可以在⼀个连接中并发多个请求或回应,⽽不⽤按照顺序⼀⼀对应。 -
服务器推送:
HTTP/2还在⼀定程度上改善了传统的「请求-应答」⼯作模式,服务不再是被动地响应,也可以主动向客户端发送消息。 -
HTTP/1.1中的管道(pipeline)传输中如果有⼀个请求阻塞了,那么队列后请求也统统被阻塞住了。HTTP/2多个请求复⽤⼀个TCP连接,⼀旦发⽣丢包,就会阻塞住所有的HTTP请求。
-
-
HTTP/3把HTTP下层的TCP协议改成了UDP。
-
HTTP/1.1如何优化:
-
缓存技术:
不含有包体的304NotModified。
-
减少重定向请求次数:
重定向的⼯作交由代理服务器完成,就能减少HTTP请求次数了。 -
合并请求:
把多个访问⼩⽂件的请求合并成⼀个⼤的请求当⼤资源中的某⼀个⼩资源发⽣变化后,客户端必须重新下载整个完整的⼤资源⽂件。
-
延迟发送请求:
只获取当前⽤户所看到的⻚⾯资源,当⽤户向下滑动⻚⾯的时候,再向服务器获取接下来的资源。
-
⽆损压缩:
⽆损压缩是指资源经过压缩后,信息不被破坏,还能完全恢复到压缩前的原样。
-
有损压缩:
有损压缩主要将次要的数据舍弃,牺牲⼀些质量来减少数据量、提⾼压缩⽐。
-
三、TCP篇
-
PSH(push):表示推送操作,就是指数据包到达接收端以后,不对其进行队列处理,而是尽可能的将数据交给应用程序处理。
-
URG(urgent):紧急标志,用于保证TCP连接不被中断,并且督促中间层设备尽快处理。
-
为什么是三次握手?不是两次、四次?
-
避免历史连接:
如果是两次握手连接,就不能判断当前连接是否是历史连接,三次握手则可以在客户端(发送方)准备发送第三次报文时,客户端因有足够的上下文来判断当前连接是否是历史连接。
客户端收到后可以根据自身的上下文,判断这是一个历史连接(序列号过期或超时),那么客户端就会发送RST(RESET)报文给服务端,表示中止这一次连接。 -
同步双方初始序列号:
ISN。
-
避免资源浪费:
如果客户端的SYN阻塞了,重复发送多次SYN报文,那么服务器在收到请求后就会建立多个冗余的无效链接,造成不必要的资源浪费。
-
-
TCP四次挥手:
-
客户端打算关闭连接,此时会发送一个TCP首部FIN标志位被置为1的报文,也即FIN报文,之后客户端进入FIN_WAIT_1状态。
服务端收到该报文后,就向客户端发送ACK应答报文,接着服务端进入CLOSED_WAIT状态。客户端收到服务端的ACK应答报文后,之后进入FIN_WAIT_2状态。
等待服务端处理完数据后,也向客户端发送FIN报文,之后服务端进入LAST_ACK状态。
客户端收到服务端的FIN报文后,回一个ACK应答报文,之后进入TIME_WAIT状态服务器收到了ACK应答报文后,就进入了CLOSE状态,至此服务端已经完成连接的关闭。
客户端在经过2MSL一段时间后,自动进入CLOSE状态,至此客户端也完成连接的关闭。
-
主动关闭连接的,才有TIME_WAIT状态。
-
服务端通常需要等待完成数据的发送和处理,所以服务端的
ACK
和FIN
一般都会分开发送,从而比三次握手导致多了一次。 -
MSL
是MaximumSegmentLifetime,报文最大生存时间,它是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。因为TCP报文基于是IP协议的,而IP头中有一个TTL
字段,是IP数据报可以经过的最大路由数,每经过一个处理他的路由器此值就减1,当此值为0则数据报将被丢弃,同时发送ICMP报文通知源主机。 -
MSL与TTL的区别:MSL的单位是时间,而TTL是经过路由跳数。
-
2MSL
的时间是从客户端接收到FIN后发送ACK开始计时的。如果在TIME-WAIT时间内,因为客户端的ACK没有传输到服务端,客户端又接收到了服务端重发的FIN报文,那么2MSL时间将重新计时。 -
TIME_WAIT等待2倍的MSL,比较合理的解释是:网络中可能存在来自发送方的数据包,当这些发送方的数据包被接收方处理后又会向对方发送响应,所以一来一回需要等待2倍的时间。防⽌旧连接的数据包、保证连接正确关闭。
-
优化2MSL:
-
net.ipv4.tcp_tw_reuse 和 tcp_timestamps:
复⽤处于TIME_WAIT的socket为新的连接所⽤。
-
net.ipv4.tcp_max_tw_buckets:
当系统中处于 TIME_WAIT 的连接⼀旦超过这个值时,系统就会将后⾯的 TIME_WAIT 连接状态重置。
-
程序中使⽤SO_LINGER:
如果 l_onoff 为⾮ 0, 且 l_linger 值为 0,那么调⽤ close 后,会⽴该发送⼀个 RST 标志给对端,该 TCP 连接将跳过四次挥⼿,也就跳过了 TIME_WAIT 状态,直接关闭。
-
-
-
SYN攻击:
-
攻击者短时间伪造不同IP地址的SYN报⽂,服务端每接收到⼀个SYN报⽂,就进⼊SYN_RCVD状态,但服务端发送出去的ACK+SYN报⽂,⽆法得到未知IP主机的ACK应答,久⽽久之就会占满服务端的SYN接收队列(未连接队列),使得服务器不能为正常⽤户服务。
-
防范:
主要有两大类,一类是通过防火墙、路由器等过滤网关防护,另一类是通过加固TCP/IP协议栈防范。
-
SYN(未完成连接建⽴)队列与Accpet(已完成连接建⽴)队列是如何⼯作的:
当服务端接收到客户端的SYN报⽂时,会将其加⼊到内核的「SYN队列」;
接着发送SYN+ACK给客户端,等待客户端回应ACK报⽂;
服务端接收到ACK报⽂后,从「SYN队列」移除放⼊到「Accept队列」;
应⽤通过调⽤accpet()socket接⼝,从「Accept队列」取出连接。
-
SYN Cookie:
当 「 SYN 队列」满之后,后续服务器收到 SYN 包,不进⼊「 SYN 队列」;
计算出⼀个 cookie 值,再以 SYN + ACK 中的「序列号」返回客户端,服务端接收到客户端的应答报⽂时,服务器会检查这个 ACK 包的合法性。如果合法,直接放⼊到「 Accept 队列」。
-
-
半关闭:
当TCP链接中A向B发送FIN请求关闭,另一端B回应ACK之后,并没有立即发送FIN给A,A方处于半连接状态(半开关),此时A可以接收B发送的数据,但是A已经不能再向B发送数据。
-
半连接:
发生在TCP三次握手中,如果A向B发起链接,B也按照正常情况响应了,但是A不进行三次握手,这就是半连接。
-
半打开:
如果一方关闭或者异常关闭(断电,断网),而另一方并不知情,这样的链接称之为半打开。解决:引入心跳机制。
-
序列号:在建⽴连接时由计算机⽣成的随机数作为其初始值,通过SYN包传给接收端主机,每发送⼀次数据,就
「累加」⼀次该「数据字节数」的⼤⼩。⽤来解决⽹络包乱序问题。 -
确认应答号:指下⼀次「期望」收到的数据的序列号,发送端收到这个确认应答以后可以认为在这个序号以前的数据都已经被正常接收。⽤来解决不丢包的问题。
-
TCP是⾯向连接的、可靠的、基于字节流的传输层通信协议。
-
MTU:⼀个⽹络包的最⼤⻓度,以太⽹中⼀般为1500字节;
MSS:除去IP和TCP头部之后,⼀个⽹络包所能容纳的TCP数据的最⼤⻓度。
-
为什么UDP头部没有「⾸部⻓度」字段,⽽TCP头部有「⾸部⻓度」字段呢:
TCP有可变⻓的「选项」字段,⽽UDP头部⻓度则是不会变化的,⽆需多⼀个字段去记录UDP的⾸部⻓度。
-
TCP数据的长度=IP总长度-IP首部长度-TCP首部长度。
-
TCP的连接状态查看,在Linux可以通过netstat-napt命令查看。
-
由IP层进⾏分⽚传输,是⾮常没有效率的,如果⼀个IP分⽚丢失,整个IP报⽂的所有分⽚都得重传,因为IP层本身没有超时重传机制,它由传输层的TCP来负责超时和重传。
所以,为了达到最佳的传输效能TCP协议在建⽴连接的时候通常要协商双⽅的MSS值,当TCP层发现数据超过
MSS时,则就先会进⾏分⽚,当然由它形成的IP包的⻓度也就不会⼤于MTU,⾃然也就不⽤IP分⽚了。经过TCP层分⽚后,如果⼀个TCP分⽚丢失后,进⾏重发时也是以MSS为单位,⽽不⽤重传所有的分⽚,⼤⼤增加了重传的效率。
-
TCP保活机制:
定义⼀个时间段,在这个时间段内,如果没有任何连接相关的活动,TCP 保活机制会开始作⽤,每隔⼀个时间间隔,发送⼀个探测报⽂,该探测报⽂包含的数据⾮常少,如果连续⼏个探测报⽂都没有得到响应,则认为当前的TCP 连接已经死亡,系统内核将错误信息通知给上层应⽤程序。
-
listen backlog:accept队列大小。
-
客户端 connect 成功返回是在第⼆次握⼿,服务端 accept 成功返回是在三次握⼿成功之后。
-
如果⼀个⼤的 TCP 报⽂被 MSS 分⽚,那么所有「分⽚都具有 TCP 头部」,因为每个 MSS 分⽚的是具有TCP 头部的TCP报⽂,那么其中⼀个 MSS 分⽚丢失,就只需要重传这⼀个分⽚就可以。
-
⼀个 TCP 连接是由四元组(源 IP 地址,源端口,⽬标 IP 地址,⽬标端口)确定的。
-
超时重传:
- RTT 就是数据从⽹络⼀端传送到另⼀端所需的时间,也就是包的往返时间。
- 超时重传时间是以 RTO (Retransmission Timeout 超时重传时间)表示,RTO应该是一个动态变化的值。RTO 也是指数上涨的。
- 超时重传时间 RTO 的值应该略⼤于报⽂往返 RTT 的值。
-
快速重传:
- 不以时间为驱动,⽽是以数据驱动重传。
- 快速重传的⼯作⽅式是当收到三个相同的 ACK 报⽂时,会在定时器过期之前,重传丢失的报⽂段。
- 它依然⾯临着另外⼀个问题。就是重传的时候,是重传之前的⼀个,还是重传所有的问题。
- SACK ( Selective Acknowledgment 选择性确认):这种⽅式需要在 TCP 头部「选项」字段⾥加⼀个 SACK 的东⻄。
- Duplicate SACK ⼜称 D-SACK 其主要使⽤了 SACK 来告诉「发送⽅」有哪些数据被重复接收。
-
滑动窗口:
-
窗口⼤⼩就是指⽆需等待确认应答,⽽可以继续发送数据的最⼤值(支持管线化的机制)。
-
累计确认或者累计应答:
ACK 600 确认应答报⽂丢失,也没关系,因为可以通过下⼀个确认应答进⾏确认,只要发送⽅收到了 ACK
700 确认应答,就意味着 700 之前的所有数据「接收⽅」都收到了。
-
通常窗口的⼤⼩是由接收⽅的窗口⼤⼩来决定的。
-
发送⽅的滑动窗⼝:使⽤三个指针来跟踪在四个传输类别中的每⼀个类别中的字节。
-
流量控制:
TCP 提供⼀种机制可以让「发送⽅」根据「接收⽅」的实际接收能⼒控制发送的数据量,这就是所谓的流量控制。
-
当发送⽅可⽤窗⼝变为 0 时,发送⽅实际上会定时发送窗口探测报⽂,以便知道接收⽅的窗⼝是否发⽣了改变。
-
接收⽅向发送⽅通告窗⼝⼤⼩时,是通过 ACK 报⽂来通告的。
-
为了防止该报文丢失造成的死锁问题,TCP 为每个连接设有⼀个持续定时器,只要 TCP 连接⼀⽅收到对⽅的零窗⼝通知,就启动持续计时器。如果持续计时器超时,就会发送窗⼝探测 ( Window probe ) 报⽂,⽽对⽅在确认这个探测报⽂时,给出⾃⼰现在的接收窗⼝⼤⼩。
-
当服务端系统资源⾮常紧张的时候,操⼼系统可能会直接减少了接收缓冲区⼤⼩,这时应⽤程序⼜⽆法及时读取缓存数据,那么这时候就有严重的事情发⽣了,会出现数据包丢失的现象。
为了防⽌这种情况发⽣,TCP 规定是不允许同时减少缓存⼜收缩窗⼝的,⽽是采⽤先收缩窗⼝,过段时间再减少缓存,这样就可以避免了丢包情况。
-
-
糊涂窗⼝综合症:
-
让接收⽅不通告⼩窗⼝给发送⽅:
当「窗⼝⼤⼩」⼩于 min( MSS,缓存空间/2 ) ,也就是⼩于 MSS 与 1/2 缓存⼤⼩中的最⼩值时,就会向发送⽅通告窗⼝为 0 ,也就阻⽌了发送⽅再发数据过来。
-
让发送⽅避免发送⼩数据:
使⽤ Nagle 算法,该算法的思路是延时处理,它满⾜以下两个条件中的⼀条才可以发送数据:
要等到窗⼝⼤⼩ >= MSS 或是 数据⼤⼩ >= MSS;
收到之前发送数据的 ack 回包。
可以在 Socket 设置 TCP_NODELAY 选项来关闭这个算法。
-
-
拥塞控制:
-
流量控制是避免「发送⽅」的数据填满「接收⽅」的缓存。
-
拥塞控制的⽬的就是避免「发送⽅」的数据填满整个⽹络。
-
拥塞窗⼝ cwnd是发送⽅维护的⼀个的状态变量,它会根据⽹络的拥塞程度动态变化的。
-
慢启动:
⼀点⼀点的提⾼发送数据包的数量。当发送⽅每收到⼀个 ACK,拥塞窗⼝ cwnd 的⼤⼩就会加 1。发包的个数呈指数性的增⻓。当 cwnd < ssthresh(慢启动⻔限) 时,使⽤慢启动算法。
-
拥塞避免:
每当收到⼀个 ACK 时,cwnd 增加 1/cwnd。线性增长。当 cwnd >= ssthresh 时,就会使⽤「拥塞避免算法」。
-
拥塞发⽣:
当发⽣了「超时重传」,则就会使⽤拥塞发⽣算法。ssthresh 设为 cwnd/2 ,cwnd 重置为 1。
-
快速恢复:
快速重传和快速恢复算法⼀般同时使⽤。
-
Fast Open:
- 在第⼀次建⽴连接的时候,服务端在第⼆次握⼿产⽣⼀个 Cookie (已加密)并通过 SYN、ACK 包⼀起发给客户端,于是客户端就会缓存这个 Cookie ,所以第⼀次发起 HTTP Get 请求的时候,还是需要 2 个 RTT 的时延;
- 在下次请求的时候,客户端在 SYN 包带上 Cookie 发给服务端,就提前可以跳过三次握⼿的过程,因为
Cookie 中维护了⼀些信息,服务端可以从 Cookie 获取 TCP 相关的信息,这时发起的 HTTP GET 请求就只需要 1 个 RTT 的时延。
-
半连接队列,也称 SYN 队列;全连接队列,也称 accepet 队列。
-
发⽣TCP 全连接队溢出的时候,后续的请求就会被丢弃。
-
close和shutdown:
- 调⽤了 close 函数意味着完全断开连接,完全断开不仅指⽆法传输数据,⽽且也不能发送数据。 此时,调⽤了close 函数的⼀⽅的连接叫做「孤⼉连接」。
- SHUT_RD(0):关闭连接的「读」这个⽅向,如果接收缓冲区有已接收的数据,则将会被丢弃,并且后续再收到新的数据,会对数据进⾏ ACK,然后悄悄地丢弃。也就是说,对端还是会接收到 ACK,在这种情况下根本不知道数据已经被丢弃了。
- SHUT_WR(1):关闭连接的「写」这个⽅向,这就是常被称为「半关闭」的连接。如果发送缓冲区还有未发送的数据,将被⽴即发送出去,并发送⼀个 FIN 报⽂给对端。
- SHUT_RDWR(2):相当于 SHUT_RD 和 SHUT_WR 操作各⼀次,关闭套接字的读和写两个⽅向。
-
TCP优化:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qL5VeEqK-1621507230809)(C:\Users\NiGo\AppData\Roaming\Typora\typora-user-images\image-20210519141322077.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R8WaxJ7b-1621507230810)(C:\Users\NiGo\AppData\Roaming\Typora\typora-user-images\image-20210519141359033.png)]
-
TCP 报⽂发出去后,并不会⽴⻢从内存中删除,因为重传时还需要⽤到它。
-
在 TCP 选项字段定义了窗⼝扩⼤因⼦,⽤于扩⼤ TCP 通告窗⼝,其值⼤⼩是 2^14,这样就使 TCP 的窗⼝⼤⼩从 16 位扩⼤为 30位(2^16 * 2^ 14 = 2^30),所以此时窗⼝的最⼤值可以达到 1GB。
-
⽹络的传输能⼒是有限的,当发送⽅依据发送窗⼝,发送超过⽹络处理能⼒的报⽂时,路由器会直接丢弃这些报⽂。因此,缓冲区的内存并不是越⼤越好。应该由带宽时延积决定。
-
带宽时延积BDP = 带宽 * RTT。由于发送缓冲区⼤⼩决定了发送窗⼝的上限,⽽发送窗⼝⼜决定了「已发送未确认」的⻜⾏报⽂的上限。因此,发送缓冲区不能超过「带宽时延积」。
-
在⾼并发服务器中,为了兼顾⽹速与⼤量的并发连接,我们应当保证缓冲区的动态调整的最⼤值达到带宽时延积,⽽最⼩值保持默认的 4K 不变即可。⽽对于内存紧张的服务⽽⾔,调低默认值是提⾼并发的有效⼿段。
-
不要在 socket 上直接设置 SO_SNDBUF 或者 SO_RCVBUF,这样会关闭缓冲区的动态调整功能。
-
四、IP篇
-
⽹络层的主要作⽤是:实现主机与主机之间的通信,也叫点对点(end to end)通信。
-
MAC 的作⽤则是实现「直连」的两个设备之间通信,⽽ IP 则负责在「没有直连」的两个⽹络之间进⾏通信传输。
-
源IP地址和⽬标IP地址在传输过程中是不会变化的,只有源 MAC 地址和⽬标MAC ⼀直在变化。
-
IP地址是以网卡来配置的,拥有多个网卡的设备会有多个IP地址。
-
主机号全为 1 指定某个⽹络下的所有主机,⽤于⼴播;主机号全为 0 指定某个⽹络。
-
⼴播地址⽤于在同⼀个链路中相互连接的主机之间发送数据包。
-
⼴播地址可以分为本地⼴播和直接⼴播两种。
在本⽹络内⼴播的叫做本地⼴播;在不同⽹络之间的⼴播叫做直接⼴播。
由于直接⼴播有⼀定的安全问题,多数情况下会在路由器上设置为不转发。
-
由于⼴播⽆法穿透路由,若想给其他⽹段发送同样的包,就可以使⽤可以穿透路由的多播。
-
⽆分类地址 CIDR:
- IP 地址被划分为两部分,前⾯是⽹络号,后⾯是主机号。
- ⼦⽹划分实际上是将主机地址分为两个部分:⼦⽹⽹络地址和⼦⽹主机地址。
-
我们最常⻅数据链路是以太⽹,它的 MTU 是 1500 字节。
-
在分⽚传输中,⼀旦某个分⽚丢失,则会造成整个 IP 数据报作废,所以 TCP 引⼊了 MSS 也就是在 TCP 层进⾏分⽚不由 IP 层分⽚,那么对于 UDP 我们尽量不要发送⼀个⼤于 MTU 的数据报⽂。
-
IPV6:
-
IPv6 地址⻓度是 128 位,是以每 16 位作为⼀组,每组⽤冒号 「:」 隔开。
-
IPv6 的地址主要有以下类型地址:
单播地址,⽤于⼀对⼀的通信;
组播地址,⽤于⼀对多的通信;
任播地址,⽤于通信最近的节点,最近的节点是由路由协议决定;
没有⼴播地址。
-
单播地址:
在同⼀链路单播通信,不经过路由器,可以使⽤链路本地单播地址,IPv4 没有此类型;
在内⽹⾥单播通信,可以使⽤唯⼀本地地址,相当于 IPv4 的私有 IP;
在互联⽹通信,可以使⽤全局单播地址,相当于 IPv4 的公有 IP。
-
IPv6 相⽐ IPv4 的⾸部改进:
- 取消了⾸部校验和字段。 因为在数据链路层和传输层都会校验,因此 IPv6 直接取消了 IP 的校验。
- 取消了分⽚/重新组装相关字段。 分⽚与重组是耗时的过程,IPv6 不允许在中间路由器进⾏分⽚与重组,这种操作只能在源与⽬标主机,这将⼤⼤提⾼了路由器转发的速度。
- 取消选项字段。 选项字段不再是标准 IP ⾸部的⼀部分了,但它并没有消失,⽽是可能出现在 IPv6 ⾸部中的
「下⼀个⾸部」指出的位置上。删除该选项字段使的 IPv6 的⾸部成为固定⻓度的 40 字节。
-
-
DNS:
- DNS 可以将域名⽹址⾃动转换为具体的 IP 地址。
- 域名的层级关系类似⼀个树状结构。
-
ARP:
- 主机会通过⼴播发送 ARP 请求,这个包中包含了想要知道的 MAC 地址的主机 IP 地址。当同个链路中的所有设备收到 ARP 请求时,会去拆开 ARP 请求包⾥的内容,如果 ARP 请求包中的⽬标 IP 地址与⾃⼰的 IP 地址⼀致,那么这个设备就将⾃⼰的 MAC 地址塞⼊ ARP 响应包返回给主机。
- 操作系统通常会把第⼀次通过 ARP 获取的 MAC 地址缓存起来。
- 那 RARP 协议正好相反,它是已知 MAC 地址求 IP 地址,通常这需要架设⼀台 RARP 服务器。
-
DHCP:
-
DHCP(动态主机配置协议)是一个局域网的网络协议。指的是由服务器控制一段IP地址范围,客户机登录服务器时就可以自动获得服务器分配的IP地址和子网掩码。
-
DHCP 发现报⽂(DHCP DISCOVER)和DHCP 提供报⽂(DHCP OFFER)使⽤的是 UDP ⼴播通信,其使⽤的⼴播⽬的地址是 255.255.255.255(端⼝ 67)。
-
DHCP 交互中,全程都是使⽤ UDP ⼴播通信。
-
每个⽹络都要配⼀个 DHCP 服务器?
解决:DHCP 中继代理,对不同⽹段的 IP 地址分配也可以由⼀个 DHCP 服务器统⼀进⾏管理。
-
-
NAT/NAPT:
-
NAT:
网络地址转换。简单的来说 NAT 就是对外部通信时,把私有 IP 地址转换成公有 IP 地址。
-
NAPT:
⽹络地址与端⼝转换 。把 IP 地址 + 端⼝号⼀起进⾏转换。
-
缺陷:
- 外部⽆法主动与 NAT 内部服务器建⽴连接,因为 NAPT 转换表没有转换记录。
- 转换表的⽣成与转换操作都会产⽣性能开销。
- 通信过程中,如果 NAT 路由器重启了,所有的 TCP 连接都将被重置。
-
解决:
-
改用IPV6。
-
NAT穿透技术:
客户端主动从 NAT 设备获取公有 IP 地址,然后⾃⼰建⽴端⼝映射条⽬,然后⽤这个条⽬对外通信,就不需要 NAT 设备来进⾏转换了。
-
-
-
ICMP:
- ICMP 全称是 Internet Control Message Protocol,也就是互联⽹控制报⽂协议。
- ICMP,是IP层的附属协议,所以属于网络层协议。
- ICMP 包头的类型字段,⼤致可以分为两⼤类:
- ⼀类是⽤于诊断的查询消息,也就是「查询报⽂类型」;
- 另⼀类是通知出错原因的错误消息,也就是「差错报⽂类型」。
-
IGMP:
- IGMP 是因特⽹组管理协议,⼯作在主机(组播成员)和最后⼀跳路由之间。
- IGMP 报⽂向路由器申请加⼊和退出组播组,默认情况下路由器是不会转发组播包到连接中的主机,除⾮主机通过 IGMP 加⼊到组播组,主机申请加⼊到组播组时,路由器就会记录 IGMP 路由器表,路由器后续就会转发组播包到对应的主机了。
- IGMP 报⽂采⽤ IP 封装,IP 头部的协议号为 2,⽽且 TTL 字段值通常为 1,因为 IGMP 是⼯作在主机与连接
的路由器之间。
-
ping(查询报文类型):
- ping 是基于 ICMP 协议⼯作的。
- 回送消息⽤于进⾏通信的主机或路由器之间,判断所发送的数据包是否已经成功到达对端的⼀种消息, ping 命令就是利⽤这个消息实现的。
- ping 使⽤了 ICMP ⾥⾯的 ECHO REQUEST(类型为 8 ) 和 ECHO REPLY(类型为 0)。
-
traceroute(差错报文类型):
-
故意设置特殊的TTL,来追踪去往⽬的地时沿途经过的路由器:
原理就是利⽤ IP 包的⽣存期限 从 1 开始按照顺序递增的同时发送 UDP 包,强制接收 ICMP 超时消息的⼀
种⽅法。 -
确定MTU:
发送主机端每次收到 ICMP 差错报⽂时就减少包的⼤⼩,以此来定位⼀个合适的 MTU 值,以便能到达⽬标主机。
-
五、网络综合篇
-
MAC地址用于在网络中唯一标示一个网卡,一台设备若有一或多个网卡,则每个网卡都需要并会有一个唯一的MAC地址。MAC地址的长度为48位(6个字节),通常表示为12个16进制数。
-
因为 HTTP 是经过 TCP 传输的,所以在 IP 包头的协议号,要填写为 06 (⼗六进制),表示协议为 TCP。
-
⽹卡驱动从 IP 模块获取到包之后,会将其复制到⽹卡内的缓存区中,接着会在其开头加上报头和起始帧分界符,在末尾加上⽤于检测错误的帧校验序列。
-
交换机:
-
交换机⼯作在 MAC 层,也称为⼆层⽹络设备;路由器工作在网络层,俗称三层网络设备。
-
计算机的⽹卡本身具有 MAC 地址,并通过核对收到的包的接收⽅ MAC 地址判断是不是发给⾃⼰的,如果不是发给⾃⼰的则丢弃;相对地,交换机的端⼝不核对接收⽅ MAC 地址,⽽是直接接收所有的包并存放到缓冲区中。因此,和⽹卡不同,交换机的端⼝不具有 MAC 地址。
-
交换机内部有一张MAC地址与网线端口的映射表,交换机根据 MAC 地址表查找 MAC 地址,然后将信号发送到相应的端⼝。
-
当 MAC 地址表找不到指定的 MAC 地址会怎么样?
将包转发到除了源端⼝之外的所有端⼝上,⽆论该设备连接在哪个端⼝上都能收到这个包。只要返回了响应包,交换机就可以将它的地址写⼊ MAC 地址表,下次也就不需要把包发到所有端⼝了。
-
-
路由器:
- 路由器的端⼝具有 MAC 地址,因此它就能够成为以太⽹的发送⽅和接收⽅;同时还具有 IP 地址,从这个意义上来说,它和计算机的⽹卡是⼀样的,只接收与⾃身地址匹配的包,遇到不匹配的包则直接丢弃。
- 电信号到达⽹线接⼝部分,路由器中的模块会将电信号转成数字信号,然后通过包末尾的 FCS 进⾏错误校验。
- 转发:
- 判断转发⽬标的第⼀步,就是根据包的接收⽅ IP 地址查询路由表中的⽬标地址栏,以找到相匹配的记录。将子网掩码和路由表中的目标地址进行与运算。实在找不到匹配路由时,就会选择默认路由。
- 包的发送需要根据路由表的⽹关列判断对⽅的ip地址,网关列为空说明已抵达终点。
- 知道对⽅的 IP 地址之后,接下来需要通过 ARP 协议根据 IP 地址查询 MAC 地址,并将查询的结果作为接收⽅MAC 地址。
- 源 IP 和⽬标 IP 始终是不会变的,⼀直变化的是 MAC 地址。
-
网络模型:
- OSI网络模型:共有7层,分别是应⽤层、表示层、会话层、传输层、⽹络层、数据链路层以及物理层。
- TCP/IP ⽹络模型:共有 4 层,分别是应⽤层、传输层、⽹络层和⽹络接⼝层。
-
Linux接受网络包的流程:
-
接受网络包后最简单的⼀种⽅式就是触发中断,也就是每当⽹卡收到⼀个⽹络包,就触发⼀个中断告诉操作系统。
-
为了解决频繁中断带来的性能开销,Linux 内核在 2.6 版本中引⼊了 NAPI 机制,它是混合「中断和轮询」的
⽅式来接收⽹络包,它的核⼼概念就是不采⽤中断的⽅式读取数据,⽽是⾸先采⽤中断唤醒数据接收的服务程序,然后 poll 的⽅法来轮询数据。
-
⽐如,当有⽹络包到达时,⽹卡发起硬件中断,于是会执⾏⽹卡硬件中断处理函数,中断处理函数处理完需要「暂时屏蔽中断」,然后唤醒「软中断」来轮询处理数据,直到没有新数据时才恢复中断,这样⼀次中断处理多个⽹络包,于是就可以降低⽹卡中断带来的性能开销。
-
-
Linux 发送⽹络包的流程:
一切准备好后,会触发软中断告诉⽹卡驱动程序,这⾥有新的⽹络包需要发送,最后驱动程序通过 DMA,从发包队列中读取⽹络包,将其放⼊到硬件⽹卡的队列中,随后物理⽹卡再将它发送出去