计算机网络方面
1.TCP与UDP的区别
(1)TCP是面向连接的;UDP是无连接的,即发送数据前不需要建立连接
(2)TCP提供可靠的服务,通过TCP传输的数据无差错、不丢失、不重复且按顺序到达;UDP尽最大努力交付,且不保证可靠交付
(3)TCP面向字节流;UDP面向报文
TCP有一个发送缓冲区,当应用程序传送的数据块过长时,TCP就可以把它划分短一些再传送,如果应用程序一次只发送一个字节,TCP也可以等到积累足够多的字节后再构成报文段发送出去;
对于UDP,应用层交给UDP多长的报文,UDP原样发送,既不会拆分,也不会合并。
TCP的优点:可靠,稳定,在数据传输前建立三次握手,并且在数据传递时,有确认、窗口、重传、拥塞控制机制。
TCP的缺点:传输慢、效率低,占用系统资源高,易攻击。
传数据之间建立连接,这样会消耗时间,而且在消息传递时,确认机制、重传机制和拥塞控制机制都会消耗大量的时间,而且要在每台设备上维护所有的传输连接。而每个连接都会占用系统的CPU、内存等资源。
UDP的优点:不可靠、不稳定
因为UDP没有TCP那些可靠的机制,在网络质量不好时很容易丢包。
UDP的优点:快、比TCP安全
UDP没有TCP的握手、确认、窗口、重传、拥塞控制等机制,udp是一个无状态的传输协议,所以他在传输数据时非常快。M没有TCP的这些机制,UDP较TCP被攻击者利用的漏洞就要少一些。UDP也是无法避免攻击的,比如:UDP flood攻击。。。
基于TCP、UDP的协议以及应用场景有哪些?
TCP:HTTP、FTP、SMTP(发送邮件)、POP3(接收邮件)
UDP:DNS(主域名称系统)、TFTP(通用文件传输协议等)、SNMP(简单网络管理协议)、实时游戏、qq聊天。
TCP应用场景:
效率要求相对低,但对准确性要求相对高。因为在传输中需要对数据确认、重发、排序等操作。比如:文件传输、接收邮件、远程登陆。
UDP应用场景:
效率要求相对高,对准确性要求相对低的场景。比如:qq聊天、在线视频、网络语音通话。
TCP如何保证可靠传输?
(1)确认应答+序号。
TCP给发送的每个包都进行编号,接受方对数据包进行排序,把有序的数据传送给应用层。
(2)校验和
TCP将保持它首部和数据的校验和。这是一个端到端的校验和,目的是监测数据在传输过程中的任何变化。如果收到段的校验和有差错,TCP将丢弃这个报文段和不确认收到此报文段。
(3)超时重传协议
当TCP发送一个段后,他启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到这个确认,将重发这个报文段。
(4)拥塞控制 和网络相关
拥塞控制是为了解决过多数据注入到网络,导致网络崩溃,超过负荷。TCP传输的过程中,发送端开始发送数据的时候,如果刚开始就发送大量的数据,那么就可能造成一些问题。网络可能在刚开始的时候就很拥挤,拥堵加剧就会产生大量的丢包。所以TCP引入了慢启动的机制,在开始发送数据前,先发送少量的数据探路。探清当前的网络状况如何,再决定多大的速度进行传输。
(5)流量控制
如果发送者发送数据过快,接收者来不及接收,就会出现分组丢失的现象,为避免分组丢失,控制发送者的发送速度,使得接收者来得及接收,这就是流量控制。
流量控制的实现是通过滑动窗口实现的,滑动窗口协议既保证了分组无差错、有序接收,也实现了流量控制。主要的方式就是接收方返回的ACK中会包含自己的接收窗口的大小,并且利用大小来控制发送方的数据发送。
TCP首部:
TCP首部占20个字节,包括:源端口、目的端口、序列号、确认号、校验和、窗口大小
2、请简单说一下你了解的端口及对应的服务
3、TCP三次握手
4、OSI七层模型与ICP/IP五层模型
OSI(Open System Interconnect)开放式系统互联
物理层:常用设备有集线器、中继器、网线等都是物理层的传输介质
链路层:交换机
网络层:IP、路由器
传输层:TCP、UDP
应用层:HTTP、HTTPS、FTP、POP3、SMTP
5、HTTP与HTTPS
HTTPS是加密的HTTP,HTTPS并不是一个新协议,而是HTTP+SSL,原本http与tcp直接通信,加上ssl后,就变成http先和ssl通信,再由ssl与TCP通信,相当于ssl嵌在了http与tcp之间
HTTP协议通常承载于TCP之上,在HTTP和TCP之间添加一个安全协议层(SSL或TSL),这个时候就成了HTTPS。
HTTP默认端口是80,HTTPS默认端口是443。
HTTP的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比HTTP协议安全。
为什么HTTPS安全?
因为网络请求需要中间很多的服务器路由的转发,而http协议是明文发送,在传输的过程中信息可能会被劫持或篡改,而如果使用HTTPS,密钥只有自己和终点站才有。HTTPS之所以安全,是因为它利用SSL/TSL协议传输。它包含证书,卸载,流量转发,负载均衡,页面适配,refer传递等,保障了传输过程中的安全性。
HTTPS使用的主要目的是提供对网站服务器的身份认证,同时保护交换数据的隐私与完整性。
HTTPS的特点:
(1)内容加密:采用混合加密技术,中间者无法直接查看明文内容;
(2)验证身份:通过证书认证客户端访问的是自己的服务器;
(3)保护数据完整性:防止传输的内容被中间者冒充或篡改。
HTTPS是如何进行加密的?
什么是对称加密?
就是有一个密钥,它可以对一段内容进行加密,加密后只能用他才能解密看到原来的内容,和生活中的钥匙差不多。
用对称加密可行吗?
如果通信双方各自持有同一个密钥,且没有别人知晓,这种方式当然可以,但是最大的问题是这个密钥怎么传输让双方知晓?如果由服务器生成一个密钥并传输给浏览器,在传输的过程中密钥可能会被别人劫持,所以这种方法不可取。
什么是非对称加密?
有两把密钥,一把公钥、一把私钥,用公钥加密的内容必须用私钥才能解开,同样,私钥加密的内容只能公钥解开。
用非对称加密可行吗?
假如服务器先把公钥直接明文传输给浏览器,之后浏览器向服务器传输数据前先用公钥加密好再传输,这样只有服务器有相应的私钥进行解密。但是这样仍不能保证从服务器到浏览器的这条路是安全的,公钥同样也会被劫持然后用该公钥解密服务器端传来的信息。
使用一组公钥私钥已经可以保证一个方向的数据传输是安全的,如果使用两对公钥私钥是不是能保证双向传输都安全了?的确可以。但是https加密方式没有采用这种,因为非对称加密算法非常耗时,而对称加密很快。所以需要对称加密与非对称加密结合。
非对称加密+对称加密
但是这样还存在一定漏洞,当服务器将公钥A传送到浏览器的过程中,中间人把数据包中的公钥A换成了自己伪造的公钥B,之后浏览器会用公钥B(浏览器不知道公钥被替换)加密对称加密的密钥X并传输到服务器端,然后中间人截获数据并用私钥B‘解密得到密钥X。
产生这个漏洞的根本原因是浏览器无法确认自己收到的公钥是不是服务器端的,所以需要用到CA证书。
CA数字证书:网站在使用https之前,需要向CA机构申请颁发一个数字证书,证书中有证书持有者、持有者公钥等信息。服务器把证书传输给浏览器,浏览器直接从证书里获取公钥就可以了。
如何防止数字证书被篡改?
数字签名:我们把证书内容生成一份“签名”,对比证书内容与签名是否一致就能察觉是否被篡改,这种技术叫数字签名。
HTTPS建立连接的过程:
(1)客户端发起加密请求,客户端主要提供的信息有可以使用的SSL版本、支持的加密方式。
(2)服务器返回相应,相应中包含CA证书(包含网站域名、公钥、数字签名等)
(3)客户端验证服务端的证书,用于客户端配置了CA机构的证书,里面包含CA公钥,所以可以匹配服务器端发送的公钥是否正确。
(4)客户端通过公钥对一对私钥进行加密发送给服务器,
(5)服务器收到后,用自己的私钥进行解密,获得一对私钥。
(6)最后客户端与服务器之间通过一对私钥对数据进行加密传输。
6、进程、线程、协程
进程:是系统分配资源和调度的基本单位,进程是一个正在运行程序的实例。
进程与程序:
- 程序是一段静态的代码;进程是一个动态运行的过程;
- 程序是产生进程的基础;进程是程序功能的体现;
进程的几种状态:
就绪状态:进程已经准备好了,已经分配到所需的资源,只要分配到CPU就能立即执行;
执行状态:进行处于就绪状态被调度后,进程进入执行状态;
阻塞状态:正在执行的进程由于某些事件(I/O请求,申请缓存区失败)而暂时无法运行,进程受到阻塞。在满足请求时进入就绪状态等待系统调度。
线程:是CPU调度和分派的基本单位。线程是进程中的一个执行流程。
区别:
(1)一个进程是一个独立的运行环境,单独占据一定的内存地址空间,它可以被看作一个程序或者一个应用。而线程是在进程中执行的一个任务。
(2)一个线程只能属于一个进程,但是一个进程可以拥有多个线程,不同的线程可以共享进程所拥有的全部资源。
(3)一个线程可以创建和撤销另一个线程;同一进程中的多个线程可以并发执行。
无论是进程还是线程,都是由操作系统所管理的。
协程:是比线程更加轻量级的存在。一个线程可以拥有多个协程。协程不是被操作系统内核所管理,而是由程序所控制(也就是在用户态执行)这样带来的好处就是性能得到了很大的提升,不会像线程切换那样消耗资源。
为什么要用到协程呢?
因为在线程中存在问题,比如在生产者/消费者模式中线程之间的运行过程:
若干个生产者线程向队列中写入数据,若干个消费者线程从队列中读取数据。
假如队列有长度限制,生产者向队列中插入数据,当队列满了时,生产者阻塞,当队列空了,消费者阻塞。所以这并不是一个高性能的实现。
为什么性能不高呢?
(1)涉及到同步锁
(2)涉及到线程阻塞状态和可运行状态之间的切换。
(3)涉及到线程上下文的切换。
以上都是非常消耗性能的。
如果改用协程,生产者生产消息后,直接通过yield跳转到消费者开始执行。待消费者执行完毕之后,切换回生产者继续生产,效率极高。
7、HTTP与TCP的区别
建立一个TCP连接需要经过“三次握手”
HTTP协议即超文本传输协议,是建立在TCP协议之上的一种应用。
HTTP连接显著的特点是客户端发送的每次请求都需要服务端回送响应,每次请求结束之后会主动释放连接。从建立连接到关闭连接的过程称为“一次连接”。
在http1.0中,客户端的每次请求都要求建立一次单独的连接,在处理完本次请求之后,会自动释放连接。
在http1.1中,在一次连接中可以处理多个请求,并且多个请求可以重叠进行,不需要等待一个请求结束后再进行下一个请求。
由于http在每次请求结束后都会主动释放连接,因此http连接是一种“短连接”,无状态的连接。
区别:
TCP就是单纯建立连接,不涉及我们需要请求的实际数据,简单的传输,而http是用来收发数据的。TCP是传输层协议,定义数据传输和连接方式的规范。
HTTP是应用层协议,定义的是传输数据的内容的规范。由请求和相应构成,是一个无状态的协议。HTTP永远都是由客户端发起请求,服务器返回请求,这样就限制了使用HTTP协议,无法实现在客户端没有发起请求的时候,服务器将消息推送给客户端。
8、死锁
死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信造成的一种阻塞现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态。
产生死锁的四个必要条件:(只要一个不满足就不会死锁)
(1)互斥条件。即某个资源在一段时间内只能由一个进程所有,不能同时被两个或两个以上的进程所有。
(2)请求和保持条件。进程获得一定资源后,又对其他资源发出请求,但是该资源可能被其他进程占用,此时请求阻塞,但是又对自己占有的资源保持不放。
(3)不可剥夺条件。是指进程以获得的资源,在未完成使用之前,不可被剥夺,只能使用完自己释放。
(4)环路等待条件。若干进程之间形成一种首尾相接的循环等待资源关系。
解决死锁的方法:
(1)死锁预防:破坏导致死锁必要条件中的任意一个就可以预防死锁。例如,要求用户申请资源时一次性申请所需要的全部资源,这就破坏了保持和等待的条件;将资源进行分层,得到上一资源后,才能够申请下一层的资源。
(2)死锁避免:避免是指进程每次申请资源时判断这些操作是否安全,例如,使用银行家算法,死锁避免算法的执行会增加系统的开销。
(3)死锁检测:死锁预防和死锁避免都是事前措施,而死锁检测是判断系统是否处于死锁状态,如果是,则执行死锁解除策略。
(4)死锁解除:这是与死锁检测结合使用的,它使用的方式就是剥夺。即将进程所拥有的资源强行进行回收,分配给其他的进程。
9、get和post的区别
(1)安全性。get请求的数据显示在url上,而post把数据放在http的包体内(request body),所以post比get更加安全。
(2)长度限制。get提交的数据最大是2k个字节(因为浏览器对url的长度有限制),而post没有限制,post发送的数据更大。
(3)get在回退按钮或刷新时是无害的,而post会重新提交数据。
(4)get产生的url地址可以收藏为书签,而post不能
(5)get请求会被浏览器主动生成缓存,而post不会,除非手动设置
(6)编码类型。get请求只能进行url编码,而post支持多种编码方式。
get:application/x-www-form-urlencoded
post:application/x-www-form-urlencoded 或 multipart/form-data。为二进制数据使用多重编码。
(7)get请求参数会被完整保留在浏览器历史纪录中,而post中的参数不会被保留。
(8)get只接受ASCLL字符的参数的数据类型,而post没有限制。
(9)get产生一个TCP数据包,post产生两个TCP数据包。
get请求,浏览器会把请求头和请求body一起发送出去,服务器响应200;而post请求,浏览器先发送请求头,当服务器响应100 continue时,浏览器才会发送request body。
因为post需要两步,时间上消耗的要多一些,但是在网络环境好的情况下,发一次包的时间和发两次包的时间差别基本上可以无视。
(10)post用于修改和写入数据,get一般用于搜索排序和筛选,目的是资源的获取。
10、HTTP1.0、HTTP1.1、HTTP2.0的关系和区别
HTTP1.0与HTTP1.1的区别
(1)长连接。
HTTP1.0每次请求都需要与服务器建立一个TCP连接,服务器处理完成之后立即断开连接,服务器不跟踪每个客户端的请求(无状态)。
HTTP1.0默认使用Connection:close,需要使用keep-alive参数来告知服务器端要建立一个长连接;在HTTP1.1中默认使用Connection:keep-alive,支持长连接,避免了连接建立和释放的开销。
(2)缓存处理。
HTTP1.0中主要使用header里的if-Modified-Since,Expires来做为缓存判断的标准。 1.0中采用的是绝对时间。
HTTP1.1则引入了更多的缓存控制策略,如Entity tag,If-None-Match等更多可供选择的缓存头来控制缓存策略。eTag是资源的唯一标识
(3)节约带宽 100状态码
HTTP1.1加入了新的状态码100(continue):允许客户端在发送请求消息body之前先用request header来试探一下服务器,看服务器要不要接收request body,再决定要不要发送request body。
HTTP1.1客户端事先发送一个只带头域的请求,如果服务器因为权限拒绝了请求,就返回响应码401(Unauthorized),这样客户端就可以不用发送请求body了,节约带宽;如果服务器接收此请求就返回响应码100,客户端就可以继续发送带实体的完整请求了。
(4)host字段
在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此请求消息中的URL并没有传递主机名,但随着虚拟主机技术的发展,一台物理服务器上可以存在多个虚拟主机,并且它们共享一个IP。
HTTP1.1的请求消息和相应消息都应支持Host头域,且请求消息中如果没有host头域会报告一个错误(400 Bad Request)。
目前http1.1存在的问题:
(1)线头阻塞,http1.1虽然采用keep-alive来解决复用TCP的问题,但是还是无法解决请求阻塞的问题。所谓请求阻塞是一条TCP连接在同一时间只允许一个请求,后面的请求需要等待前面的请求返回相应之后再请求。
之所以会有这个问题就是因为http1.x需要每条请求都是可识别的,按顺序发送,否则服务器端就无法判断该响应哪个具体的请求了。
(2)多个TCP连接
虽然http1.1管道化可以支持请求并发,但是浏览器很难实现,chrome、firefox等都禁用了管道化。所以1.1版本请求并发依赖于多个TCP连接,建立TCP连接的成本很高,还会存在慢启动的问题。
(3)头部冗余,采用文本格式
http1.1版本采用的是文本格式,首部未压缩,每一个请求都会带上cookie、user-agent等完全相同的首部。
(4)客户端需要主动请求
HTTP1.1与HTTP2.0的区别
(1)二进制分帧
http1.x采用的是文本格式传输数据,而http2.0采用的是二进制格式传输。http2.0是二进制协议。
在应用层和传输层之间增加了一个二进制分帧层。在分帧层,会将传输的信息分割成更小的消息和帧,并采用二进制格式进行编码。将头部信息封装到header frame,将request body封装到data frame中。
http1.x是基于文本格式的,由于文本的表现形式有很多种,要做到健壮性考虑的场景必然很多,而二进制分帧只认0和1的组合。
(2)多路复用
上面提到的http1.1的线头阻塞和多个TCP连接的问题,http2.0的多路复用完美解决。http2.0让所有的通信都在一个TCP连接上完成,真正实现了请求的并发。
每个请求以stream的方式传输,每个stream都有唯一表示,connection连接一旦建立,后续的请求都可以复用这个connection并且可以同时发送,服务端根据stream的唯一标识来响应对应的请求。
在http2.0中有两个非常重要的概念:帧和流。帧是最小的数据单位。HTTP2.0的传输是基于二进制帧的,每一个TCP连接中承载了多个双向流通的流,每个流都有唯一的标识,而流就是由二进制帧组成的。二进制帧的头部信息会标识自己属于哪个流,所以这些帧是可以交错传输的,然后在接收端通过帧头的信息组装成完整的数据。
(3)头部压缩
http1.1不支持header数据的压缩,每次请求的header都会带有大量的信息,而且每次都要重复发送。http2.0使用HPACK算法对header的数据进行压缩,这样数据体积小了,传输就会更快。
头部压缩需要在浏览器和服务器之间:
- 维护一份相同的静态字典,包括常见的头部名称以及常见的头部名称和值的组合;
- 维护一份相同的动态字典,可以动态的添加内容;
- 通过静态Huffman编码对传输的首部字段进行编码。
静态字典:
假如我们要传输method:GET,那么我们只需要传输字典里面method:GET对应的索引值就可以了,一个字节搞定。但是像cookie、user-agent这种静态字典中只有首部而没有值的首部,第一次传输需要user-agent在静态字典中的索引以及它的实际值,值会用静态Huffman编码来减小体积。
第一次传输过user-agent之后,浏览器和服务器就会把它添加到自己的动态字典中,后续传输就可以传输索引了,一个字节搞定。
(4)服务器推送
服务端根据客户端的请求,提前返回多个相应,推送额外的资源给客户端。
例如:客户端请求index.html,服务器端能够额外推送script.js和style.css。实现原理就是客户端发送请求时,服务器端能够分析这个页面所依赖的其他资源,主动推送到客户端的缓存。当客户端收到原始网页的请求时,他需要的资源已经位于缓存中了。
针对每一个希望发送的资源,服务器会发送一个PUSH_PROMISE帧,客户端可以通过发送RST_STREAM帧来拒绝推送(当资源已经位于缓存)。这一步操作要先于父响应。客户端了解到服务端打算推送哪些资源,就不会再为这些资源创建重复请求。
HTTP2.0的弊端:
主要是底层支撑的TCP协议的问题。
因为http2.0使用了多路复用,一般来说同一域名下只需要使用一个TCP连接。当这个连接中出现了丢包的情况,会导致http2.0的表现情况不如http1.1了。
因为在出现丢包的情况下,整个TCP都要开始等待重传,也就导致了后面的所有数据都被阻塞了。但是对于http1.1来说,可以开启多个TCP连接,出现这种情况反倒会只影响其中一个连接,剩余的TCP连接还可以正常传输数据。
操作系统
(1)为什么要分内核态和用户态?
内核态:CPU可以访问内存所有数据,包括外围设备,例如硬盘,网卡。CPU也可以将自己从一个程序切换到另一个程序。
用户态:只能受限的访问内存,且不允许访问外围设备。占用CPU的能力被剥夺,CPU资源可以被其他程序获取。
原因:
由于需要限制不同程序之间的访问能力,防止他们获取别的程序的内存数据,或者获取外围设备的数据,并发送到网络。
为了安全性。在cpu的一些指令中,有的指令如果用错,将会导致整个系统崩溃。分了内核态和用户态之后,当用户需要操作这些指令时候,内核为其提供了API,可以通过系统调用陷入内核,让内核去执行这些操作。
假如没有这种内核态和用户态之分,程序随随便便就能访问硬件资源,比如分配内存,程序能随意读取所有的内存空间,如果程序员一不小心将不适当的内容写到了不该写的地方,就很可能导致系统崩溃。用户程序是不可信的,很容易造成系统崩溃。
(2)进程之间通信的方式
进程间通信的主要方式有:管道、FIFO、消息队列、信号量等。
管道:(无名管道)
管道只能在具有公共祖先的两个进程之间使用,通常,一个管道由一个进程创建,在进程调用fork之后,这个管道就能在父进程和子进程之间使用了。
FIFO:(命名管道)
与无名管道不同的是,其可以在不相关的程序之间交换数据。
信号量:
信号量是一个计数器,主要用于实现进程间的互斥与同步,而不是用于存储进程间通信数据。