无题
八股文集合
计算机网络
介绍一下TCP/IP模型和OSI模型的区别
OSI和TCP/IP都是一个计算机进行通信的一种体系,而OSI模型师国际组织制定的一个标准体系,TCP/IP是实际网络通信中的实际的体系结构。
OSI自底向上分为物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。
TCP/IP分四层,每个层负责特定的网络功能。
自底向上是网络接口层,这层对应OSI的数据链路层和物理层,,这层负责物理传输媒介的定义和管理,比如有线的以太网传输,无线的WIFI传输,此外,网络接口层还管理硬件地址(MAC地址)的管理。
然后是网络层,这层对应OSI的网络层,主要协议是IP,他负责数据包的路由和转发,选择一个最佳路径来将数据包从源主机传送到目标主机。IP协议使用IP地址来进行逻辑地址寻址。
传输层对应OSI的传输层,这层负责应用与应用间的数据传输。主要的传输协议是TCP和UDP。TCP提供可靠的数据传输,UDP提供不可靠的实时传输。
应用层对应OSI的应用层、表示层和会话层,他用于网络上的各种应用提供服务,比如网页浏览,文件传输等。
以上就是osi和tcp/ip的区别了。
从输入URL到页面展示到底发生了什么
个人版:
首先是用户输入url当按下回车键的时候浏览器会先解析url
把url分成
1、协议:http还是https
2、域名:类似于www.baidu.com
3、端口:如果是http的话默认是80端口https默认是443端口
4、路径:/index.html类似这种访问域名服务器下的哪个路径
5、还有一些请求参数等类似于?id=1这种
当解析完url之后再进行DNS解析,就是将域名转换成对应的ip地址就称为DNS解析了,转换的流程是先从浏览器中查看是否有之前的浏览缓存记录,如果浏览器中没有就从操作系统的host文件中查找,如果hosts文件也没有就从ISP的DNS服务器中查找域名对应的IP地址,就是中国移动那种运营商的DNS服务器中查找,如果还没有就从根DNS服务器中查找,直到找到对应的ip地址。找到对应的IP地址后客户端和服务器会开始建立三次握手根服务器建立tcp连接,客户端向服务端发送同步报文的信息,类似于跟服务器说我想跟你建立连接了,然后服务器向客户端发送确认收到连接信息的响应信息,然后客户端再向服务器发送我收到连接建立成功的信息了,
- 第一次握手:客户端发送
SYN=1
,随机生成初始序号ISN=x
; - 第二次握手:服务器确认
SYN=1
,并回复SYN=1, ACK=1
,同时生成自己的 ISN=y; - 第三次握手:客户端发送
ACK=1
,确认服务器的 ISN=y+1。
如果是https连接的话在建立完tcp连接后还需要
- 开始进行 TLS/SSL 握手,包括:
- 客户端发送
ClientHello
(支持的加密套件、协议版本等) - 服务器回应
ServerHello
+ 证书(包含公钥) - 双方协商密钥、验证身份、完成加密通道建立
- 加密通道建立成功后,才开始发送加密的 HTTP 请求
- 客户端发送
然后这样tcp连接就建立成功了,tcp建立成功后,客户端会向服务器发送请求,包含请求头,请求体等信息,然后服务端就会响应信息,包含响应头,响应体,还有cookie等信息,然后连接保持的字段有个keep-alive这个字段来确认保持连接的状态,燃弧响应后浏览器会解析响应信息,会先解析HTML文件然后形成DOM树,然后再解析CSS文件生成CSSOM,最后将两个图层合并就形成一个好看的页面了,之后再解析JS文件,解析JS文件的过程中会导致页面的重排和重绘,也会有一些外部的资源文件的加载,异步的请求等。
然后会连接可能保持也可能断开,如果数据传输完成了,断开的是四次挥手,客户端向服务器发送我要断开连接的消息,然后服务端向客户端发送我收到断开连接申请的信息,然后再发送我已经断开连接的信息,然后客户端向服务端发送我收到已经断开连接的信息了,以上就是所有。
- 在 HTTP 请求结束后,如果设置了
Connection: close
,则立即断开; - 如果是
keep-alive
,则 TCP 连接暂时保留,等待下一次复用; - 如果一段时间没有新请求(例如服务器设置 idle=60s),连接会被关闭。
HTTP请求报文和响应报文是怎样的,有哪些常见的字段?
HTTP报文分为请求报文和响应报文。
1、请求报文主要由请求行、请求头、空行和请求体构成
请求行包括:
方法:指定要执行的操作,如GET、POST、PUT、DELETE等
资源路径:请求的资源的URI(统一资源标识符)
HTTP版本:使用的HTTP协议版本如HTTP/1.1或HTTP/2.0
请求头字段比较多,通常包含:
Host:请求的服务器域名
Accept: 客户端能够处理的媒体类型
Accept-Encoding:客户端能够解码的内容编码
Authorization:用于认证的凭证信息,比如token数据
Content-Length:请求体长度
Content-Type:请求体的媒体类型
Cookie: 存储在客户端的cookie数据
If-None-Match:资源的ETag值,用于缓存控制
Connection:管理连接的选项比如keep-alive
空行是请求头和请求体之间的空行,主要用于分隔请求头和请求体。请求体通常用于POST和PUT请求,包含发送给服务器的JSON数据。
2、响应报文,HTTP响应报文是服务器向客户端返回的数据格式用于传达服务器对客户端请求的处理结果以及相关数据。通常包含状态行、响应头、空行、响应体。
状态行:HTTP版本、状态码和状态消息比如HTTP/1.1 200 OK
响应头也是以键值对的形式提供信息,一些常见的相应头包括
Content-Type:指定相应主题的媒体类型
Content-Length:指定响应主题的长度(字节数)。
Server:指定服务器的信息
Expires:响应的过期时间,之后内容被认为是过时的。
Etag:响应体的实体标签,用于缓存和条件请求。
Last-Modified:资源最后被修改的日期和时间。
Location:在重定向时指定新的资源位置
Set-Cookie:在响应中设置Cookie
Access-Control-Allow-Origin:夸资源共享CORS策略,指定哪些域可以访问资源。
空行是在响应头和响应体之间表示响应头结束。而响应体式服务端实际传输的数据,可以是文本、HTML页面、图片、视频等,也可能是空。
HTTP有哪些请求方式
- GET:请求指定的资源。
- POST:向指定资源提交数据进行处理请求(例如表单提交)。
- PUT:更新指定资源。
- DELETE:删除指定资源。
- HEAD:获取报文首部,不返回报文主体。
- OPTIONS:查询服务器支持的请求方法。
- PATCH:对资源进行部分更新。
GET请求和POST请求的区别
- 用途:GET请求通常用于获取数据,POST请求用于提交数据。
- 数据传输:GET请求将参数附加在URL之后,POST请求将数据放在请求体中。
- 安全性:GET请求由于参数暴露在URL中,安全性较低;POST请求参数不会暴露在URL中,相对更安全。
- 数据大小:GET请求受到URL长度限制,数据量有限;POST请求理论上没有大小限制。
- 幂等性:GET请求是幂等的,即多次执行相同的GET请求,资源的状态不会改变;POST请求不是幂等的,因为每次提交都可能改变资源状态。
- 缓存:GET请求可以被缓存,POST请求默认不会被缓存。
HTTP中常见的状态码有哪些
1xx:表示加载信息很少见
200 :表示客户端请求成功
201:创建了新资源
204:无内容,服务器成功处理请求,但未返回任何内容
301:永久重定向
302:临时重定向
304:请求的内容没有修改过,所以服务器返回响应时,不会返回网页内容,而是使用缓存。
401:请求需要身份验证
403:请求的对应资源禁止被访问
404:服务器无法找到对应的资源
500:服务器内部错误
503:服务不可用
什么是强缓存和协商缓存
强缓存和协商缓存是HTTP缓存机制的两种类型,他们用于减少服务器的负担和提高网页加载速度。
1、强缓存:客户端在没用向服务发送请求的情况下,直接从本地缓存中获取资源。
Expires强缓存:这个是用于设置强缓存时间,此时间范围内,从内存中读取缓存并返回。但是因为Expires判断强缓存过期的机制是获取本地时间戳,与之前拿到的资源文件中的Expires字段的时间做比较来判断是否需要对服务器发起请求。这里有一个巨大的漏洞,如果我本地时间不准怎么办?所以目前已经被废弃了。
Cachee-Control强缓存:目前使用的强缓存是通过HTTP响应头中的Cache-Control字段实现,通过max-age来告诉浏览器在指定时间内可以直接使用缓存数据,无需再次请求。
2、协商缓存:当强缓存失效时,浏览器会发送请求到服务器,通过ETag或Last-Modified等HTTP响应头与服务器进行验证,以确定资源是否被修改。如果资源未修改,服务器服务器返回304 Not Modified状态码,告知浏览器使用本地缓存。如果资源已经修改,则返回新的资源,浏览器更新本地缓存。这种凡是需要与服务器通信,但可以确保用户总是获取最新的内容。
如果是基于缓存的资源获取的话一个是基于Last-Modified一个是基于ETag。
- 如果是基于Last-Modified的协商缓存,Last-Modified是资源的最后修改时间,服务器在响应头部中返回。当客户端读取到Last-modified的时候,会在下次的请求标头中携带一个字段If-Modified-Since,而这个请求头中的If-Modified-Since就是服务器第一次修改时候给他的时间服务器比较请求中的If-Modified-Since值与当前资源的Last-Modified值,如果比对的结果是没有变化,表示资源未发生变化,返回状态码304 Not Modified,如果比对的结果说资源已经更新了,就会给浏览器正常资源,返回200状态。
但是这种协商缓存有两个缺点:
- 因为是更改文件修改时间来判断的,所以在文件内容本身不修改的情况下,依然有可能更新文件修改时间(比如修改文件名再改回来),这样有可能文件内容明明没修改但是缓存依然失效了。
- 当文件在极短时间内完成修改的时候(比如几百毫秒)。因为文件修改事件记录的最小单位是秒,所以,如果文件在几百毫秒内完成修改的话,文件修改时间不会改变,这样即使文件内容修改了,依然不会返回新的文件。
- 基于ETag的协商缓存:将原先协商缓存的比较时间戳的形式修改成了比较文件指纹(根据文件内容计算出的唯一哈希值)
- ETag是服务器为资源生成的唯一标识符(文件指纹),可以是根据文件内容计算出的哈希值,服务端将其和资源一起放回给客户端。
- 客户端在请求头部的If-None-Match字段中携带上次响应的ETag值。
- 服务器比较请求中的If-None-Match值与当前资源的ETag值,如果匹配,表示资源未发生变化,返回状态码
304 Not Modified
。如果两个文件指纹不吻合,则说明文件被更改,那么将新的文件指纹重新存储到响应头的ETag中并返回给客户端
HTTPS和HTTP有哪些区别
两者的主要区别在于安全性和数据加密:
- 加密层:
HTTPS
在HTTP
的基础上增加了SSL/TLS
协议作为加密层,确保数据传输的安全性。而HTTP
数据传输是明文的,容易受到攻击。 - HTTP 连接建立相对简单, TCP 三次握手之后便可进行 HTTP 的报文传输。而 HTTPS 在 TCP 三次握手之后,还需进行 SSL/TLS 的握手过程,才可进入加密报文传输。
- 端口:
HTTPS
通常使用端口443
,而HTTP
使用端口80。 - HTTPS 协议需要向 CA 申请数字证书,来保证服务器的身份是可信的。
HTTPS的工作原理(HTTPS建立连接的过程)
1、客户端向服务端发送HTTPS请求Client Hello发送过去,这里包含了客户端支持的TLS版本、加密套件以及生成了第一个随机数给服务端
2、服务端打招呼,发送了Server Hello发送给客户端(这里包含确认TLS版本、选择使用的加密套件,以及生成第2个随机数),然后还把证书和公钥发送给客户端
3、这时候客户端生成了第三个随机数,这里称为预主密钥,并用之前接受到的公钥进行加密发送给服务器
4、这时候服务端接收到公钥加密后的字符串之后,利用自己的密钥进行解密,这样客户端和服务端都知道了预主密钥了。
5、这时候客户端和服务端利用第一个随机数和第二个随机数和预主密钥通过加密算法计算得出会话密钥。后面传输的数据都是用会话密钥进行加密。后面的是对称加密的,前面是非对称加密的,也就是说知道会话密钥之后就能自动解密会话密钥加密的字符串了。
https真的安全吗?
假设服务器的网址是http://www.baidu.com那么如果用户输入了baidu.com的话这个是http请求然后会返回302再重定向到https://www.baidu.com那么这时候就会有问题了,假设有一个第三方的人,在302重定向的时候拦截你的请求然后返回给你一个很像的网站,这样就使用不了https了,那这种一般会给浏览器一个警告,警告用户你访问的不是一个https的网站以此来把这个责任推给用户,这个问题还解决不了。此外国际组织还设置了一个新的状态码307状态码,之前重定向是302,现在这个307状态码限制用户访问的location不能改变就比如访问baidu.com那么后面的网址不能更改,只能往前面加https://www.baidu.com来限制重定向到别的网站,但是还是解决不了之前那个拦截请求的问题。最终的解决方案是HSTS 预加载列表,类似于在浏览器设置白名单如果输入baidu.com,浏览器也会自动跳转到 HTTPS,不会发出明文请求。
HTTPS
主要基于SSL/TLS
协议,确保了数据传输的安全性和完整性, 其建立连接并传输数据的过程如下:
- 密钥交换:客户端发起HTTPS请求后,服务器会发送其公钥证书给客户端。
- 证书验证:客户端会验证服务器的证书是否由受信任的证书颁发机构(
CA
)签发,并检查证书的有效性。 - 加密通信:一旦证书验证通过,客户端会生成一个随机的对称加密密钥,并使用服务器的公钥加密这个密钥,然后发送给服务器。
- 建立安全连接:服务器使用自己的私钥解密得到对称加密密钥,此时客户端和服务器都有了相同的密钥,可以进行加密和解密操作。
- 数据传输:使用对称加密密钥对所有传输的数据进行加密,确保数据在传输过程中的安全性。
- 完整性校验:SSL/TLS协议还包括消息完整性校验机制,如消息认证码,确保数据在传输过程中未被篡改。
- 结束连接:数据传输完成后,通信双方会进行会话密钥的销毁,以确保不会留下安全隐患。
TCP和UDP的区别
- TCP是面向连接的协议,需要在数据传输前建立连接;UDP是无连接的,不需要建立连接。
- TCP提供可靠的数据传输,保证数据包的顺序和完整性;UDP不保证数据包的顺序或完整性。
- TCP具有拥塞控制机制,可以根据网络状况调整数据传输速率;UDP没有拥塞控制,发送速率通常固定。
- TCP通过滑动窗口机制进行流量控制,避免接收方处理不过来;UDP没有流量控制。
- TCP能够检测并重传丢失或损坏的数据包;UDP不提供错误恢复机制。
- TCP有复杂的报文头部,包含序列号、确认号等信息;UDP的报文头部相对简单。
- 由于TCP的连接建立、数据校验和重传机制,其性能开销通常比UDP大;UDP由于简单,性能开销小。
- 适用场景:TCP适用于需要可靠传输的应用,如网页浏览、文件传输等;UDP适用于对实时性要求高的应用,如语音通话、视频会议等。
TCP连接如何确保可靠性
TCP通过差错控制(序列号、确认应答、数据校验)、超时重传、流量控制、拥塞控制等机制,确保了数据传输的可靠性和效率。
- 序列号:每个TCP段都有一个序列号,确保数据包的顺序正确。
- 数据校验:TCP使用校验和来检测数据在传输过程中是否出现错误,如果检测到错误,接收方会丢弃该数据包,并等待重传。
- 确认应答:接收方发送ACK确认收到的数据,如果发送方在一定时间内没有收到确认,会重新发送数据。
- 超时重传:发送方设置一个定时器,如果在定时器超时之前没有收到确认,发送方会重传数据。
- 流量控制:TCP通过滑动窗口机制进行流量控制,确保接收方能够处理发送方的数据量。
- 拥塞控制:TCP通过算法如慢启动、拥塞避免、快重传和快恢复等,来控制数据的发送速率,防止网络拥塞。
既然提到了拥塞控制,那你能说说说拥塞控制是怎么实现的嘛
TCP拥塞控制可以在网络出现拥塞时动态地调整数据传输的速率,以防止网络过载。TCP拥塞控制的主要机制包括以下几个方面:
- 慢启动(Slow Start): 初始阶段,TCP发送方会以较小的发送窗口开始传输数据。随着每次成功收到确认的数据,发送方逐渐增加发送窗口的大小,实现指数级的增长,这称为慢启动。这有助于在网络刚开始传输时谨慎地逐步增加速率,以避免引发拥塞。
- 拥塞避免(Congestion Avoidance): 一旦达到一定的阈值(通常是慢启动阈值),TCP发送方就会进入拥塞避免阶段。在拥塞避免阶段,发送方以线性增加的方式增加发送窗口的大小,而不再是指数级的增长。这有助于控制发送速率,以避免引起网络拥塞。
- 快速重传(Fast Retransmit): 如果发送方连续收到相同的确认,它会认为发生了数据包的丢失,并会快速重传未确认的数据包,而不必等待超时。这有助于更快地恢复由于拥塞引起的数据包丢失。
- 快速恢复(Fast Recovery): 在发生快速重传后,TCP进入快速恢复阶段。在这个阶段,发送方不会回到慢启动阶段,而是将慢启动阈值设置为当前窗口的一半,并将拥塞窗口大小设置为慢启动阈值加上已确认但未被快速重传的数据块的数量。这有助于更快地从拥塞中恢复。
TCP流量控制是怎么实现的?
流量控制就是让发送方发送速率不要过快,让接收方来得及接收。利用滑动窗口机制就可以实施流量控制,主要方法就是动态调整发送方和接收方之间数据传输速率。
- 滑动窗口大小: 在TCP通信中,每个TCP报文段都包含一个窗口字段,该字段指示发送方可以发送多少字节的数据而不等待确认。这个窗口大小是动态调整的。
- 接收方窗口大小: 接收方通过TCP报文中的窗口字段告诉发送方自己当前的可接收窗口大小。这是接收方缓冲区中还有多少可用空间。
- 流量控制的目标: 流量控制的目标是确保发送方不要发送超过接收方缓冲区容量的数据。如果接收方的缓冲区快满了,它会减小窗口大小,通知发送方暂停发送,以防止溢出。
- 动态调整: 发送方会根据接收方的窗口大小动态调整发送数据的速率。如果接收方的窗口大小增加,发送方可以加速发送数据。如果窗口大小减小,发送方将减缓发送数据的速率。
- 确认机制: 接收方会定期发送确认(ACK)报文,告知发送方已成功接收数据。这也与流量控制密切相关,因为接收方可以通过ACK报文中的窗口字段来通知发送方它的当前窗口大小。
UDP怎么实现可靠传输
UDP它不属于连接型协议,因而具有资源消耗小,处理速度快的优点,所以通常音频、视频和普通数据在传送时使用UDP较多,因为它们即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。传输层无法保证数据的可靠传输,只能通过应用层来实现了。实现的方式可以参照tcp可靠性传输的方式,只是实现不在传输层,实现转移到了应用层。关键在于两点,从应用层角度考虑:
(1)提供超时重传,能避免数据报丢失。
(2)提供确认序列号,可以对数据报进行确认和排序。
本端:首先在UDP数据报定义一个首部,首部包含确认序列号和时间戳,时间戳是用来计算RTT(数据报传输的往返时间),计算出合适的RTO(重传的超时时间)。然后以等-停的方式发送数据报,即收到对端的确认之后才发送下一个的数据报。当时间超时,本端重传数据报,同时RTO扩大为原来的两倍,重新开始计时。
对端:接受到一个数据报之后取下该数据报首部的时间戳和确认序列号,并添加本端的确认数据报首部之后发送给对段。根据此序列号对已收到的数据报进行排序并丢弃重复的数据报。
为什么是三次握手?
- 三次握手的过程
- 第一次握手:客户端向服务端发送一个SYN(同步序列号)报文,请求建立连接,客户端进入SYN_SENT状态
- 第二次握手:服务器收到SYN报文后,如果同意建立连接,则会发送一个SYN-ACK(同步确认)报文作为相应,同时进入SYN_RCVD状态
- 第三次握手:客户端收到服务器的SYN-ACK报文后,会发送一个ACK(确认)报文作为最终相应,之后客户端和服务器都进入ESTABLISHED状态,连接建立成功。
- 为什么需要三次握手
通过三次握手,客户端和服务端都能够确认对方的接收和发送能力。第一次握手确认了客户端到服务器的通道是开放的;
第二次握手确认了服务器到客户端的通道是开放的;
第三次握手则确认了客户端接收到服务器的确认,从而确保了双方的通道都是可用的。
如果是两次握手的话,现在客户端向服务端发送SYN报文(同步序列号),这时候如果网络不好导致SYN报文没发送过去,就会进行重传,这时候新的SYN包发过去了,如果同意连接服务端就会发送客户端SYN-ACK包进行同步确认,然后客户端接收到SYN-ACK报文后会发送ACK确认报文给服务端,这时候对于客户端来说认为是建立了一个TCP连接,然后这时候之前旧的SYN报文网络好了,又发送给了服务端,这时候服务端又发送ACK给客户端,但是客户端由于没有发送SYN报文就把这个ACK过滤掉了,但是对于服务端来说就认为建立了两个TCP连接,客户端和服务端的连接个数就不匹配了。所以两次握手不行。
如果是多次握手的话,会造成资源的浪费最终可以优化成三次握手。
为什么是四次挥手?
- 四次挥手的过程
- 第一次挥手:客户端发送一个FIN报文给服务端,表示自己要断开数据传送,报文中会制定一个序列号(seq=x)。然后,客户端进入FIN-WAIT-1状态。
- 第二次挥手:服务端收到FIN报文后,回复ACK报文给客户端,且把客户端的序列号值+1,作为ACK+1报文的序列号(seq=x+1)。然后,服务端进入CLOSE-WAIT``(seq=x+1)状态,客户端进入FIN-WAIT-2状态。
- 第三次挥手:服务端也要断开连接时,发送FIN报文给客户端,且指定一个序列号(seq=y+1),随后服务端进入LAST-ACK状态。
- 第四次挥手:客户端收到FIN报文后,发出ACK报文进行应答,并把服务端的序列号值+1作为ACK报文序列号(seq=y+2)。此时客户端进入TIME-WAIT状态。服务端在收到客户端的ACK报文后进入CLOSE状态。如果客户端等待2MSL没有收到回复,也就是等待一段时间后,才关闭连接。(这是由于如果一段时间后服务端没有收到客户端的ACK包就会重新发送FIN包,然后重新发送ACK包,刷新超时时间,确保服务端收到最后的ACK包)
- 为什么需要四次挥手
TCP
是全双工通信,可以双向传输数据。任何一方都可以在数据传送结束后发出连接释放的通知,待对方确认后进入半关闭状态。 当另一方也没有数据再发送的时候,则发出连接释放通知,对方确认后才会完全关闭TCP
连接。因此两次挥手可以释放一端到另一端的TCP
连接,完全释放连接一共需要四次挥手。
只有通过四次挥手,才可以确保双方都能接收到对方的最后一个数据段的确认,主动关闭方在发送完最后一个ACK
后进入TIME-WAIT
状态,这是为了确保被动关闭方接收到最终的ACK
,如果被动关闭方没有接收到,它可以重发FIN
报文,主动关闭方可以再次发送ACK
。
而如果使用三次挥手,被动关闭方可能在发送最后一个数据段后立即关闭连接,而主动关闭方可能还没有接收到这个数据段的确认。
HTTP的Keep-Alive是什么?TCP 的 Keepalive 和 HTTP 的 Keep-Alive 是一个东西吗?
1、HTTP的Keep-Alive是叫HTTP长连接,因为由于TCP连接一次只能发送一次请求和响应,每次请求和响应都会重新连接,这种称为HTTP短连接,就会很耗费资源,这时候HTTP1.1之后就实现了HTTP的Keep-Alive实现了一使用同一个TCP连接来发送和接受多个HTTP的请求和响应,避免了多次连接建立和释放的开销,这是HTTP的长连接。通过设置HTTP头Connection:keep-alive来实现。
那这个长连接怎么关闭?是在接收端会设置一个定时器,如果超过了这个时间没再次发送请求,就会在HTTP头中设置Connection:close来关闭长连接。
2、而TCP的Keepalive是由TCP层(内核态)实现的,称为TCP的保活机制,是在TCP连接的时候,有一段时间没发送连接和请求了,通过TCP的保活机制来确认另一端是否还存活,是否有效。这个机制会发送一个小的探测包来检查连接是否仍然有效。
这里的TCP的keepalive不只是支持http,还支持ftp和smtp的,他是一个能力,类似于gc(内存管理机制,自动回收不再使用的内存空间)。
DNS的查询过程
DNS
用来将主机名和域名转换为IP地址, 其查询过程一般通过以下步骤:
- 本地DNS缓存检查:首先查询本地DNS缓存,如果缓存中有对应的IP地址,则直接返回结果。
- 如果本地缓存中没有,则会向本地的DNS服务器(通常由你的互联网服务提供商(ISP)提供, 比如中国移动)发送一个DNS查询请求。
- 如果本地DNS解析器有该域名的ip地址,就会直接返回,如果没有缓存该域名的解析记录,它会向根DNS服务器发出查询请求。根DNS服务器并不负责解析域名,但它能告诉本地DNS解析器应该向哪个顶级域(.com/.net/.org)的DNS服务器继续查询。
- 本地DNS解析器接着向指定的顶级域名DNS服务器发出查询请求。顶级域DNS服务器也不负责具体的域名解析,但它能告诉本地DNS解析器应该前往哪个权威DNS服务器查询下一步的信息。
- 本地DNS解析器最后向权威DNS服务器发送查询请求。 权威DNS服务器是负责存储特定域名和IP地址映射的服务器。当权威DNS服务器收到查询请求时,它会查找
"example.com"
域名对应的IP地址,并将结果返回给本地DNS解析器。 - 本地DNS解析器将收到的IP地址返回给浏览器,并且还会将域名解析结果缓存在本地,以便下次访问时更快地响应。
- 浏览器发起连接: 本地DNS解析器已经将IP地址返回给您的计算机,您的浏览器可以使用该IP地址与目标服务器建立连接,开始获取网页内容。
CDN是什么,有什么作用?
CDN是一种分布式网络服务,通过将内容存储在分布式的服务器上,使用户可以从距离较近的服务器获取所需的内容,从而加速互联网上的内容传输。
- 就近访问:CDN 在全球范围内部署了多个服务器节点,用户的请求会被路由到距离最近的 CDN 节点,提供快速的内容访问。
- 内容缓存:CDN 节点会缓存静态资源,如图片、样式表、脚本等。当用户请求访问这些资源时,CDN 会首先检查是否已经缓存了该资源。如果有缓存,CDN 节点会直接返回缓存的资源,如果没有缓存所需资源,它会从源服务器(原始服务器)回源获取资源,并将资源缓存到节点中,以便以后的请求。通过缓存内容,减少了对原始服务器的请求,减轻了源站的负载。
- 可用性:即使某些节点出现问题,用户请求可以被重定向到其他健康的节点。
Cookie和Session是什么?区别是什么?
Cookie
和 Session
都用于管理用户的状态和身份, Cookie
通过在客户端记录信息确定用户身份,Session
通过在服务器端记录信息确定用户身份。
- Cookie
- 通常,服务器会将一个或多个
Cookie
发送到用户浏览器,然后浏览器将这些Cookie
存储在本地。 - 服务器在接收到来自客户端浏览器的请求之后,就能够通过分析存放于请求头的
Cookie
得到客户端特有的信息,从而动态生成与该客户端相对应的内容。
- Session
客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。这就是Session
。Session 主要用于维护用户登录状态、存储用户的临时数据和上下文信息等。服务器为每个用户分配一个唯一的Session ID
,通常存储在Cookie
中。
由于HTTP是无状态的所以需要Cokkie和Session来记录用户的状态信息,比如账号、用户昵称等。
(2) Cookie和Session的区别?
- 存储位置:
Cookie
数据存储在用户的浏览器中,而Session
数据存储在服务器上。 - 数据容量:
Cookie
存储容量较小,一般为几 KB。Session
存储容量较大,通常没有固定限制,取决于服务器的配置和资源。 - 安全性:由于
Cookie
存储在用户浏览器中,因此可以被用户读取和篡改。相比之下,Session 数据存储在服务器上,更难被用户访问和修改。 - 生命周期:
Cookie
可以设置过期时间,Session
依赖于会话的持续时间或用户活动。 - 传输方式:
Cookie
在每次HTTP
请求中都会被自动发送到服务器,而Session ID
通常通过Cookie
或 URL 参数传递。
操作系统
进程和线程之间有什么区别
进程是资源分配和调度的基本单位。
线程是程序执行的最小单位,线程是进程的子任务,是进程内的执行单元。 一个进程至少有一个线程,一个进程可以运行多个线程,这些线程共享同一块内存。
资源开销:
- 进程:由于每个进程都有独立的内存空间,创建和销毁进程的开销较大。进程间切换需要保存和恢复整个进程的状态,因此上下文切换的开销较高。
- 线程:线程共享相同的内存空间,创建和销毁线程的开销较小。线程间切换只需要保存和恢复少量的线程上下文,因此上下文切换的开销较小。
通信与同步:
- 进程:由于进程间相互隔离,进程之间的通信需要使用一些特殊机制,如管道、消息队列、共享内存等。
- 线程:由于线程共享相同的内存空间,它们之间可以直接访问共享数据,线程间通信更加方便。
安全性:
- 进程:由于进程间相互隔离,一个进程的崩溃不会直接影响其他进程的稳定性。
- 线程:由于线程共享相同的内存空间,一个线程的错误可能会影响整个进程的稳定性。
并行和并发有什么区别
- 并行是在同一时刻执行多个任务。
- 并发是在相同的时间段内执行多个任务,任务可能交替执行,通过调度实现。
并行是指在同一时刻执行多个任务,这些任务可以同时进行,每个任务都在不同的处理单元(如多个CPU核心)上执行。在并行系统中,多个处理单元可以同时处理独立的子任务,从而加速整体任务的完成。
并发是指在相同的时间段内执行多个任务,这些任务可能不是同时发生的,而是交替执行,通过时间片轮转或者事件驱动的方式。并发通常与任务之间的交替执行和任务调度有关。
解释一下用户态和核心态,什么场景下,会发生内核态和用户态的切换?
- 用户态和内核态的区别
用户态和内核态是操作系统为了保护系统资源和实现权限控制而设计的两种不同的CPU运行级别,可以控制进程或程序对计算机硬件资源的访问权限和操作范围。
- 用户态:在用户态下,进程或程序只能访问受限的资源和执行受限的指令集,不能直接访问操作系统的核心部分,也不能直接访问硬件资源。
- 核心态:核心态是操作系统的特权级别,允许进程或程序执行特权指令和访问操作系统的核心部分。在核心态下,进程可以直接访问硬件资源,执行系统调用,管理内存、文件系统等操作。
- 在什么场景下,会发生内核态和用户态的切换
- 系统调用:当用户程序需要请求操作系统提供的服务时,会通过系统调用进入内核态。
- 异常:当程序执行过程中出现错误或异常情况时,CPU会自动切换到内核态,以便操作系统能够处理这些异常。
- 中断:外部设备(如键盘、鼠标、磁盘等)产生的中断信号会使CPU从用户态切换到内核态。操作系统会处理这些中断,执行相应的中断处理程序,然后再将CPU切换回用户态。
什么是死锁,如何避免?
死锁是当系统中有两个或者多个进程在进程中,因为争夺资源而造成的情况,当每个进程都持有一定的资源并且等待其他进程释放他们所需要的资源,如果这个资源被其他进程占有并且不释放,就会导致死锁。
死锁只有同时满足下面四个条件才会发生:
- 互斥条件:一个进程占用了某个资源时,其他进程无法同时占用该资源。
- 请求保持条件:一个进程因为请求资源而阻塞的时候,不会释放自己的资源。
- 不可剥夺条件:资源不能被强制性地从一个进程中剥夺,只能由持有者自愿释放。
- 循环等待条件:多个进程之间形成一个循环等待资源的链,每个进程都在等待下一个进程所占有的资源。
避免死锁:通过破坏死锁的四个必要条件之一来预防死锁。比如破坏循环等待条件,让所有进程按照相同的顺序请求资源。 检测死锁:通过检测系统中的资源分配情况来判断是否存在死锁。例如,可以使用资源分配图或银行家算法进行检测。 解除死锁:一旦检测到死锁存在,可以采取一些措施来解除死锁。例如,可以通过抢占资源、终止某些进程或进行资源回收等方式来解除死锁。
介绍一下几种经典的锁
- 互斥锁:互斥锁是一种最常见的锁类型,用于实现互斥访问共享资源。在任何时刻,只有一个线程可以持有互斥锁,其他线程必须等待直到锁被释放。这确保了同一时间只有一个线程能够访问被保护的资源。
- 自旋锁:自旋锁是一种基于忙等待的锁,即线程在尝试获取锁时会不断轮询,直到锁被释放。
其他的锁都是基于这两个锁的
- 读写锁:允许多个线程同时读共享资源,只允许一个线程进行写操作。分为读(共享)和写(排他)两种状态。
- 悲观锁:认为多线程同时修改共享资源的概率比较高,所以访问共享资源时候要上锁
- 乐观锁:先不管,修改了共享资源再说,如果出现同时修改的情况,再放弃本次操作。
讲一讲我理解的虚拟内存
虚拟内存是指在每一个进程创建加载的过程中,会分配一个连续虚拟地址空间,它不是真实存在的,\而是*通过映射与实际物理地址空间*对应,这样就可以使每个进程看起来都有自己独立的连续地址空间,并允许程序访问比物理内存RAM
更大的地址空间, 每个程序都可以认为它拥有足够的内存来运行。
需要虚拟内存的原因:
- 内存扩展: 虚拟内存使得每个程序都可以使用比实际可用内存更多的内存,从而允许运行更大的程序或处理更多的数据。
- 内存隔离:虚拟内存还提供了进程之间的内存隔离。每个进程都有自己的虚拟地址空间,因此一个进程无法直接访问另一个进程的内存。
- 物理内存管理:虚拟内存允许操作系统动态地将数据和程序的部分加载到物理内存中,以满足当前正在运行的进程的需求。当物理内存不足时,操作系统可以将不常用的数据或程序暂时移到硬盘上,从而释放内存,以便其他进程使用。
- 页面交换:当物理内存不足时,操作系统可以将一部分数据从物理内存写入到硬盘的虚拟内存中,这个过程被称为页面交换。当需要时,数据可以再次从虚拟内存中加载到物理内存中。这样可以保证系统可以继续运行,尽管物理内存有限。
- 内存映射文件:虚拟内存还可以用于将文件映射到内存中,这使得文件的读取和写入可以像访问内存一样高效。
你知道的线程同步的方式有哪些
线程同步机制是指在多线程编程中,为了保证线程之间的互不干扰,而采用的一种机制。常见的线程同步机制有以下几种:
- 互斥锁:互斥锁是最常见的线程同步机制。它允许只有一个线程同时访问被保护的临界区(共享资源)
- 条件变量:条件变量用于线程间通信,允许一个线程等待某个条件满足,而其他线程可以发出信号通知等待线程。通常与互斥锁一起使用。
- 读写锁: 读写锁允许多个线程同时读取共享资源,但只允许一个线程写入资源。
- 信号量:用于控制多个线程对共享资源进行访问的工具。
有哪些页面置换算法
页面置换算法(Page Replacement Algorithm)是操作系统用于管理内存的一种关键技术,特别是在虚拟内存系统中。当程序运行时,其所需的数据和指令可能不会全部同时驻留在物理内存中,而是根据需要在磁盘和内存之间进行交换。当一个进程访问的页面当前不在内存中(即发生缺页中断),操作系统需要从磁盘加载所需的页面到内存中。如果此时内存已经满了,则必须选择一个或多个已经在内存中的页面将其移出以腾出空间,这个过程就是页面置换。
当一个进程访问的数据不在内存中,需要从磁盘加载进来,但如果内存已满,就必须先替换掉一个内存中的页面,这个替换过程就叫做页面置换。
常见页面置换算法有最佳置换算法(OPT)、先进先出(FIFO)、最近最久未使用算法(LRU)、时钟算法(Clock) 等。
- 最近最久未使用算法
LRU
:LRU算法基于页面的使用历史,通过选择最长时间未被使用的页面进行置换。 - 先进先出
FIFO
算法:也就是最先进入内存的页面最先被置换出去。 - 最不经常使用
LFU
:淘汰访问次数最少的页面,考虑页面的访问频率。 - 时钟算法
CLOCK
:Clock算法的核心思想是通过使用一个指针(称为时钟指针)在环形链表上遍历,检查页面是否被访问过, 当需要进行页面置换时,Clock算法从时钟指针的位置开始遍历环形链表。 如果当前页面的访问位为0,表示该页面最久未被访问,可以选择进行置换。将访问位设置为1,继续遍历下一个页面。 如果当前页面的访问位为1,表示该页面最近被访问过,它仍然处于活跃状态。将访问位设置为0,并继续遍历下一个页面如果遍历过程中找到一个访问位为0的页面,那么选择该页面进行置换。 - 最佳置换算法: 该算法根据未来的页面访问情况,选择最长时间内不会被访问到的页面进行置换。那么就有一个问题了,未来要访问什么页面,操作系统怎么知道的呢?操作系统当然不会知道,所以这种算法只是一种理想情况下的置换算法,通常是无法实现的。
熟悉哪些Linux命令
1、文件操作:
- ls:列出目录内容。
- cd:进入指定目录
- pwd:显示当前工作目录
- cp:复制文件或目录
- mv:移动或重命名文件
- rm:删除文件或目录
- touch:创建空文件或更新文件时间戳
2、文件内容查看
- cat:查看文件内容
- head:查看文件的前几行
- tail:查看文件的后几行,常用于查看日志文件
3、文件编辑
- vi或vim:强大的文本编辑器
4、权限管理
- chmod:更改文件或目录的访问权限
- chown:更改文件或目录的所有者或所属组
5、磁盘管理
- df:查看磁盘空间使用情况。
6、网络管理
- ifconfig或ip addr :查看和配置网络接口
- ping:查看网络状态和统计信息
- netstat:查看网络状态和统计信息。
- ssh:安全远程登录
7、进程管理
- ps:查看当前运行的进程。
- kill:杀掉某进程。
8、软件包管理(根据Linux发行版不同,命令可能有所不同)
- apt-get(Ubuntu):安装、更新和删除软件包
- npm install(CentOS的)
Linux中如何查看一个进程,如何杀死一个进程,如何查看某个端口有没有被占用
- 查看进程:用ps命令查看当前运行的进程,比如ps aux可以列出所有进程及其详细信息。
- 杀死进程:首先用ps或top命令找到进程的pid(进程ID)。然后用kill命令加上进程ID来结束进程,例如kill -9 PID. -9是强制杀死进程的信号。
- 查看端口占用:使用Isof -i: 端口号 可以查看占用特定端口的进程。或者用netstat -tulnp | grep 端口号,这会显示监听在该端口的服务及其进程ID。
说一下select\poll\epoll
什么是I/O多路复用?
简单来说,就是:
一个线程同时监听多个网络连接(文件描述符),一旦某个连接有数据可读或可写,就通知程序去处理它。
这在服务器开发中非常有用,比如一个 Web 服务器要同时处理成千上万个客户端的连接请求。
- select:这个是一个最古老的I/O多路复用机制,他可以监视多个文件描述符的可读、可写和错误状态。然而,但是它的效率可能随着监视的文件描述符的数量的增加而降低。
- poll:poll是select的一种改进,他使用轮询方式来检查多个文件描述符的状态,避免了select中文件描述符数量有限的问题。但对于大量的文件描述符,poll的性能也可能变得不足够高校。
- epoll:epoll是Linux特有的I/O多路复用机制,相较于select和poll,它在处理大量文件描述符时更加高校。epoll使用时间通知的方式,只有在文件描述符就绪时才会通知应用程序,而不需要应用程序的轮询。
总结:select
是最早的 I/O
多路复用技术,但受到文件描述符数量和效率方面的限制。poll
克服了文件描述符数量的限制,但仍然存在一定的效率问题。epoll
是一种高效的I/O多路复用技术,尤其适用于高并发场景,但它仅在 Linux
平台上可用。一般来说,epoll
的效率是要比 select
和 poll
高的,但是对于活动连接较多的时候,由于回调函数触发的很频繁,其效率不一定比 select
和 poll
高。所以 epoll
在连接数量很多,但活动连接较小的情况性能体现的比较明显。
技术 | 类比 |
---|---|
Blocking I/O | 每个快递员都直接送到你家 |
select/poll | 你每天去快递柜一个一个找有没有你的包裹 |
epoll | 包裹到了,快递柜自动发短信提醒你取件 |
一条SQL查询语句是如何执行的?
- 连接器:连接器负责跟客户端建立连接、获取权限、维持和管理连接。
- 查询缓存:MYSQL拿到一个查询请求后,会先到查询缓存看看,之前是不是执行过这条语句。之前执行过的语句及其结果可能会以key-value对的形式,被直接缓存在内存中。
- 分析器:你输入的是由多个字符串和空格组成的一条SQL语句,MYSQL需要识别出里面的字符串分别是什么,代表什么。
- 优化器:优化器是在表里面有多个索引的时候,决定使用哪个索引;或者在一个语句有多表关联(join)的时候,决定各个表的连接顺序。
- 执行器:MYSQL通过分析器知道了你要作什么,通过优化器知道了该怎么做,于是就进入了执行器阶段,开始执行语句。
事务的四大特性 有哪些?
事务的四大特性通常被称为ACID特性
- 原子性:确保事务的所有操作要么全部执行成功,要么全部失败回滚 ,不存在部分策划给你共的情况。
- 一致性:事务在执行前后,数据库从一个一致性状态转变到另一个一致性状态。(例子:银行转账,A=100,B=100,那么一致性就是A=50,B=150,而不是中间态A=50,B=100)
- 隔离性:多个事务并发执行时,每个事务都应该被隔离开来,一个事务的执行不应该影响其他事务的执行。
- 持久性:一旦事务被提交,它对数据库的改变就是永久性的,即使在系统故障或崩溃后也能够保持。
数据库的事务隔离级别有哪些?
读未提交:
- 允许一个事务读取另一个事务尚未提交的数据修改。
- 最低的隔离级别,存在脏读,不可重复读和幻读的问题。
读已提交
- 一个事务只能读取已经提交的数据。其他事物的修改在该事务提交之后才可见。
- 解决了脏读问题,但仍可能出现不可重复读和幻读。
可重复读
- 事务执行期间,多次读取同一数据会得到相同的结果,即在事务开始和结束之间,其他事务对数据的修改不可见。
- 解决了不可重复读问题,但仍可能出现幻读
序列化
- 最高的隔离级别,确保事物之间的并发执行效果与串行执行的效果相同,即不会出现脏读,不可重复读和幻读。
这里顺便讲一下
脏读,不可重复读和幻读是什么
脏读就是读到了脏数据,举个例子A和B转账,A一开始查询有100块然后B给A转账转了50,然后B转账失败了,但是这时候A读取数据读到了150,B回滚了,所以其实A并没有150还是100,所以读到了脏数据。
不可重复读还是刚刚的例子,A在一个事务里面查询两次,第一次查询有100然后B给A转账成功并且提交了事务,这时候A的事务还没有提交,A再次查询发现有150了,这就是不可重复读,因为B的事务影响到了A的事务,所以违反了原子性。
幻读是针对数据个数的,A在一个事务中有两个查询,第一次查询商品个数有50个商品,然后B在数据库中增加了一个商品,并且B提交了事务,然后A的事务中再次查询商品个数,发现有51条数据,这就叫幻读。
不可重复读针对的是update,幻读针对的是insert或者delete.