菜鸟笔记
提升您的技术认知

面试题

实现一个LRU Cache 算法LRU Cache C++三种解法java实现LRU算法及编码实现LRU策略缓存LRU算法常见缓存算法和LRU的c++实现设计循环双端队列(deque)LRU 缓存结构 (c++ 哈希双链表实现)LRU缓存机制删除单链表中的指定节点Linux 内核经典面试题拼多多社招面经:Redis是重点,讲一讲redis的内存模型线程、进程、协程的区别C++经典面试题面试官:我们只想要这样的C++工程师Linux C/C++ 学习路线链表操作汇总C++11的智能指针面试题浏览器中输入url后发生的事情常用的限流算法HTTP协议和HTTPS协议面试题网络编程面试题目总结c++后台面试题目如何实现LRU算法?如何寻找无序数组中的第K大元素?布隆过滤器 - 如何在100个亿URL中快速判断某URL是否存在?如何实现大整数相加?C++面试题及基本知识点总结C++给定出栈序列判定是否合法消息队列面试题要点redis缓存击穿,失效以及热点key解决方案网页在浏览器上的渲染过程几种限流算法lru算法例题C/C++常见面试知识点总结附面试真题----20210529更新引入MQ消息队列的作用及其优缺点MySQL面试篇社招三年后端面试题60道测开面试题,背完直接涨工资二叉树的层序遍历(两种方法实现)Bitmap 海量数据处理字符串倒序输出的五种方法C语言 输入10个数,统计出并输出正数、负数和0的个数字节三面:如何设计一个高并发系统架构,网络 面试36问,DDos攻击原理C++线程池使用 C++11 编写可复用多线程任务池

架构,网络 面试36问,DDos攻击原理

阅读 : 927

TCP 链接

三次握手:

  1. 首先服务器端处于LISTEN状态。
  2. 当客户端想要建立连接时,他将发送一个SYN包,序列号假如为u。客户端进入SYN_SENT状态。
  3. 当服务器端收到了这个SYN包,如果服务器同意建立连接,他将发送一个SYN,ACK包,序列号假如为v,确认号为u+1。服务器端进入SYN_RECD状态。
  4. 当客户端收到了服务器端的SYN,ACK包,它将再次确认,向服务器发送一个ACK包,序列号为u+1,确认号为v+1。此时客户端进入ESTABLISHED状态。
  5. 当服务器端收到了客户端的ACK包,也将进入ESTABLISHED状态。

四次挥手:

  1. 当客户端想要断开连接时,发送一个FIN数据包,序列号为u,确认号为v,客户端进入FIN_WAIT1状态。
  2. 当服务器端收到这个FIN包,他知道了客户端想要断开连接,它会发送一个ACK包对它进行确认,序列号为v,确认号为u+1。此时服务器进入CLOSE_WAIT状态。
  3. 当客户端收到了服务器端发送的ACK确认包,他知道了服务器了解了自己想要断开连接。此时客户端进入FIN_WAIT2状态。
  4. 当服务器端的数据都发送结束了,它将断开服务器端到客户端的连接,它向客户端发送一个FIN包,序列号假设为w,确认号依旧为u+1。此时服务器端进入LAST_ACK阶段。
  5. 当客户端收到了服务器端的FIN包,他知道了服务器也要断开连接,它向服务器发送一个ACK确认包,序列号为u+1,确认号为w+1,然后进入TIME_WAIT阶段等待2倍MSL,在这个期间如果没有继续收到服务器端的FIN包,就进入了CLOSED阶段。
  6. 服务器端收到客户端的ACK确认包,进入CLOSED阶段。

为什么不能两次挥手?

  • 防止网络中失效的连接请求到达服务器端,如果只有两次握手,服务器端将建立连接,是资源浪费。举个例子,客户端发送了一个连接请求,但是这个请求在网络中阻塞了,超过重传时间后客户端又再次发送连接请求包,建立连接,完成服务,断开连接。然后之前滞留的包又到达了服务器端,如果两次握手,连接就建立了。并且客户端不会请求关闭,资源浪费。
  • 通过三次握手,让客户端和服务器端都知道了自己的发送和接收没问题。第一次握手,暂时没有什么,第二次握手,让服务器端知道了自己的接收没问题,第三次握手,让客户端知道了自己的发送和接收均无问题,当服务器端收到了客户端的最后一次确认,它也将知道自己的接收没有问题。
     

为什么需要TIME_WAIT状态?为什么TIME_WAIT的时长是2*MSL?

原因1:防止连接关闭时四次挥手中的最后一次ACK丢失:

TCP需要保证每一包数据都可靠的到达对端,包括正常连接状态下的业务数据报文,以及用于连接管理的握手、挥手报文,这其中在四次挥手中的最后一次ACK报文比较特殊,TIME_WAIT状态就是为了应对最后一条ACK丢失的情况。

TCP保证可靠传输的前提是收发两端分别维护关于这条连接的状态信息(TCB控制块),当发生丢包时进行ARQ重传。如果连接释放了,就无法进行重传,也就无法保证发生丢包时的可靠传输。

对于最后一条ACK,如果没有TIME_WAIT状态,主动关闭一方(客户端)就会在收到对端(服务器)的FIN并回复ACK后 直接从FIN_WAIT_2 进入 CLOSED状态,并释放连接,销毁TCB实例。此时如果最后一条ACK丢失,那么服务器重传的FIN将无人处理,最后导致服务器长时间的处于 LAST_ACK状态而无法正常关闭(服务器只能等到达到FIN的最大重传次数后关闭)。

至于将TIME_WAIT的时长设置为 2MSL,是因为报文在链路中的最大生存时间为MSL(Maximum Segment Lifetime),超过这个时长后报文就会被丢弃。TIME_WAIT的时长则是:最后一次ACK传输到服务器的时间 + 服务器重传FIN 的时间,即为 2MSL。

原因2:防止新连接收到旧链接的TCP报文:

TCP使用四元组区分一个连接(源端口、目的端口、源IP、目的IP),如果新、旧连接的IP与端口号完全一致,则内核协议栈无法区分这两条连接。

2*MSL 的时间足以保证两个方向上的数据都被丢弃,使得原来连接的数据包在网络中都自然消失,再出现的数据包一定是新连接上产生的。

TCP连接如何保证数据有效性

  1. 检验和:数据收发方在进行数据传输时,都会先计算校验和,如果不一致,就说明数据传输有误。
  2. 确认应答,序列号:TCP在进行数据传输时都是进行编号的,每次接收方返回ACK时都有确认序列号。
  3. 超时重传:如果发送方发送数据一段时间后没有收到ACK,那么就重新发送数据。
  4. 连接管理:TCP通过三次握手建立连接,四次挥手断开连接。
  5. 流量控制:根据接收端的能力进行数据发送。TCP协议报头包含16位的窗口大小,接收方会在返回数据时,将自己的即时窗口大小填入,发送方就会根据报文中窗口的大小控制发送速度。
  6. 拥塞控制:会像探路一样,先发送小数据,防止拥塞。刚开始发送数据的时候,拥塞窗口是1,以后每次收到ACK,则拥塞窗口+1,然后将拥塞窗口和收到的窗口取较小值作为实际发送的窗口,如果发生超时重传,拥塞窗口重置为1。这样做的目的就是为了保证传输过程的高效性和可靠性。

TCP与UDP的区别

它们都是传输层协议。

  1. TCP是面向连接的,发送数据前先要建立连接,UDP是面向无连接的,发送数据前不需要建立连接。
  2. TCP面向字节流的,UDP是面向报文的。
  3. TCP是可靠的,TCP可以保证数据无差错,不重复,不丢失,按需到达。UDP是不可靠的,它只能尽最大努力交付。
  4. TCP是点到点通信,UDP支持一对一,一对多,多对一,多对多。
  5. TCP首部开销大,20个字节。UDP首部开销小,8个字节。

TCP的优点与缺点

优点:可靠,稳定

缺点:传输数据之前先要建立连接。慢,效率低且占用资源多。

解释一下确认重传机制,讲讲窗口滑动

TCP对字节编号,当发送方在重传时间内没有收到期望的确认包,它就认为自己之前发送的包在网络中丢失,就会进行重传。

为了进行流量控制,在发送方和接收方都都保持一个窗口,窗口左边是已经发送且已经确认的数据。窗口右边是还未发送的数据。窗口里分为两个部分,左边是已发送未确认的部分,右边是此窗口状态下还可以发送的数据。
 

ISO七层结构,网络层和传输层的底层实现

ISO七层模型:

物理层处于OSI参考模型的最低层。物理层的主要功能是利用物理传输介质为数据链路层提供物理连接,以透明地传送比特流。
数据链路层在物理层提供比特流传输服务的基础上,在通信实体之间建立数据链路连接,传送以帧为单位的数据,通过差错控制、流量控制方法,变有差错的物理线路为无差错的数据链路。
网络层主要任务是通过执行路由选择算法,为报文分组通过通信子网选择最适当的路径。它是OSI参考模型七层中最复杂的一层。
传输层是向用户提供可靠的端到端服务,透明地传送报文 。
会话层的主要目的是组织同步的两个会话用户之间的对话,并管理数据的交换。
表示层主要用于处理两个通信系统间信息交换的表示方式,它包括数据格式变换、数据加密与解密、数据压缩与恢复等功能。
应用层是OSI参考模型的最高层。应用层不仅要提供应用进程所需要信息交换和远程操作,而且还要作为应用进程的用户代理,完成一些为进行语义上有意义的信息交换所必须的功能。综上所述可知,ISO/OSI开放系统互连七层参考模型***能最复杂的一层是网络层。

网络层和传输层底层实现:

TCP/IP UDP/IP?

传输层有2个协议:TCP(Transmission Control Protocol),传输控制协议 UDP(User Datagram Protocol),用户数据报协议

网络层数据包(IP数据包,Packet)由首部、数据2部分组成
数据:很多时候是由传输层传递下来的数据段(Segment)

TCP和UDP在程序设计的时候应该注意的点?

  • TCP适用于对网络通讯质量要求高的场景,比如文件传输。
  • UDP适用于对网络通讯质量要求不高,要求网络通讯速度尽可能快的场景。比如QQ语音,QQ视频。

HTTP 状态码有哪些

1XX:信息性状态码
2XX:成功状态码
3XX:重定向状态码
4XX:客户端错误状态码
5XX:服务器错误状态码

100 Continue:表示到目前为止都很正常,客户端可以继续发送请求或者忽略这个响应。
200 OK
204 No Content:请求已经成功处理,但是返回的响应报文不包含实体的主体部分。一半只需要从客户端往服务器端发送信息,而不需要返回数据时使用。
206 Partial Content:表示客户端进行了范围请求,响应报文包含由Content-Range指定范围的实体内容。
301 Moved Permanently:永久性重定向
302 Found:临时性重定向
303 See Other:和302有着相同的功能,但是303明确要求客户端应该采用GET方法获取资源。
304:Not Modified:如果请求报文首部包含一些条件,例如:If-Modified-Since,如果不满足条件,则服务器会返回304状态码。
307 Temporary Redirect:临时性重定向,与302的含义类似,但是307要求浏览器不会把重定向请求的POST方法改成GET方法。
400 Bad Request:请求报文中存在语法错误。
401 Unauthorized:状态码表示发送的请求需要有认证信息,如果之前已经进行过一次请求,则表示用户验证失败。
403 Forbidden:请求被拒绝。
404 Not Found:未发现资源
405 Method Not Allowed:方法不允许。
500 Internal Server Error:服务器正在执行请求时发生错误。
503:Server Unavailable:服务器暂时处于超负载或者正在进行停机维护,现在无法处理请求。

http无状态

协议对交互场景没有记忆能力。浏览器对服务器完成一次资源请求后,再次对服务器进行资源请求,服务器不会记得之前的行为。
 

http无状态怎么解决

采用cookie和session

session和cookie区别

  1. 保存的位置不同:cookie保存在浏览器端,session保存在服务端。
  2. 使用方式不同:Cookie 存储在浏览器中,容易被恶意查看。如果非要将一些隐私数据存在 Cookie 中,可以将 Cookie 值进行加密,然后在服务器进行解密。
    对于大型网站,如果用户所有的信息都存储在 Session 中,那么开销是非常大的,因此不建议将所有的用户信息都存储到 Session 中。
  3. 存储内容不同:cookie只能存储字符串,而session存储结构类似于hashtable的结构,可以存放任何类型。
  4. 存储大小:cookie最多可以存放4k大小的内容,session则没有限制。

session放本地的方法

将seesion数据加密,然后存储在cookie中。

session是如何识别用户的?

通过cookie存储一个session_id,然后具体的数据则是保存在session中。如果用户已经登录,则服务器会在cookie中保存一个session_id,下次再次请求的时候,会把该session_id携带上来,服务器根据session_id在session库中获取用户的session数据。就能知道该用户到底是谁,以及之前保存的一些状态信息。

http 长连接 短连接

  • http长连接指的是使用完一次http服务之后连接不断开,可以继续下一次服务使用。
  • 短连接指的是每请求完一个资源,就断开连接,想要再次请求,就得再建立连接。

下载一个超大文件为什么网速会越来越快,解释背后的技术

拥塞窗口机制:慢开始。

为什么要有滑动窗口?

首先,TCP是全双工协议,意味着会话双方可以同时接收和发送数据,其中会话双方都各自维护一个发送和接收窗口,各自的接收窗口取决于应用、系统、硬件的限制,发送窗口则要求取决于对端通告的接收窗口,要求两者相同。可以想象一下,如果发送端发送数据过快超过接收端的数据处理速率,这就意味着接收端会产生数据溢出的情况。为了避免这种情况,所以才出现滑动窗口来解决流量控制的问题。

滑动窗口的机制:

  1. 发送窗口只有接收到发送窗口内字节的确认ACK,才会移动发送窗口的左边界;
  2. 接收窗口只有在前面所有的数据段都确认接收到的情况下,才会移动接收窗口的左边界,以此确保对端会对未收到的数据进行重传。
  3. 遵循快速重传,累计确认,选择确认等规则

拥塞控制的过程

在TCP双方建立逻辑链接关系时,发送端设置拥塞窗口cwnd=1,还设置了慢开始门限ssthresh。

  1. 在执行慢开始算法时,发送方每收到一个对新报文段的确认时,拥塞窗口cwnd+1,然后开始下一轮的传输(此时cwnd=2,发送方发送2个报文段,接收方回复2个ACK确认,然后cwnd=4,以此类推,这个过程是指数增长的),直到cwnd>=ssthresh时,开始改用拥塞避免算法。
  2. 使用拥塞避免算法时,每个传输轮次不再是指数增长的,拥塞窗口cwnd只能线性+1。(假设24个报文段中,发送方只收到20个确认ACK,意味着这个过程丢失了4个报文段,一段时间后这4个丢失报文段的超时重传计时器超时了,发送方会误认为网络发生阻塞(实际也可能是数据包在网络中丢失),然后更改了慢开始门限ssthresh和重置cwnd=1,并开始重新开始慢开始算法,导致传输效率降低)
  3. 为了避免这个误判,引入了快重传。快重传其实就是使发送方尽快进行重传,而不是等待超时计时器超时才重传,要求接收方要立即发送确认,即使收到了失序的报文段也要立即发出对已收到的报文段的重复确认,发送方一旦收到3个连续的重复确认,则将相应的报文段立即重传,不必等待超时计时器超时。(对于个人丢失的报文段,发送方也不会出现超时重传,也不会误判网络阻塞)
  4. 快恢复,发送发一旦收到三个重复的确认,就知道现在只是丢失了个别报文段,于是不再使用慢开始算法,而是执行快恢复算法(发送方将慢开始门限ssthresh和拥塞窗口cwnd调整为当前窗口的一般,执行拥塞避免算法)
     

发送方维护一个叫做拥塞窗口cwnd的状态变量,其值取决于网络的拥塞程度,并且动态变化;
发送方将拥塞窗口作为发送窗口,即swnd=cwnd
维护一个慢开始门限ssthresh状态变量
当cwnd<ssthresh时,使用慢开始算法
当cwnd=ssthresh时,既可以使用慢开始算法,也可以使用拥塞避免算法
当cwnd>ssthresh时,改用拥塞避免算法

对比滑动窗口和拥塞窗口

滑动窗口是控制接收以及同步数据范围的,用于流量控制,在接收端使用,由于TCP是双全工,所以两边都有滑动窗口;
拥塞窗口是控制发送速率的,避免发的过多接收端处理不过来,在发送端使用。

其中,两个窗口的维护是独立的,滑动窗口主要由接收端反馈缓存情况来维护,而拥塞 窗口主要由发送方根据拥塞控制算法检测网络拥塞情况程度来决定的。

http 和 https 的区别

  1. https协议需要到CA申请证书,一般免费证书较少,因而需要一定费用。        
  2. http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl/tls加密传输协议。        
  3. http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。        
  4. http的连接很简单,是无状态的;HTTPS协议是由SSL/TLS+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

https 加密过程

首先要知道,加密方式有对称加密和非对称加密两种

对称加密:指的是明文在加密和暗文在解密过程中都使用同一个密钥。

优势:

  • 双方不用在网络中传输秘钥文件
  • 加解密速度快

劣势:

  • 无法多client,只能用少数几个信任的client
  • server更新秘钥文件就得更新client端,不方便

非对称加密:一般使用两个密钥,一个是称为‘公钥’,另一个叫做‘私钥’。
公钥和私钥是配对的,其最大的缺点就是运算速度慢,比对称加密慢许多。私钥就可以对密文解密也可以对明文进行加密,公钥也一样。一般情况来说客户端可以获得公钥,而服务器一般使用私钥。

优势:可以不用事先约定好的秘钥,动态生成

劣势: 加解密耗时耗资源

而HTTPS采用的是对称加密和非对称加密的混合加密方法。为什么不使用对称加密或者非对称加密?

对称加密:如果客户端直接将密钥进行明文传输给服务器,那么黑客也能获得密钥,那么后续的加密操作就没有任何用处了。因此,客户端在传输密钥的时候必须要给密钥进行加密。

非对称加密:对称加密的效率比非对称加密高很多, 因此只是在开始阶段协商密钥的时候使用非对称加密, 后续的传输仍然使用对称加密.
不过这种方法也有一定问题:如果客户端获取的公钥是黑客伪造的,那么其后续的加密就没有用了。

为了解决这一问题:通常,在客户端和服务器建立的时候,服务器给客户端返回一个证书,该证书里面就包含公钥,也包含了网站的信息。

对称 + 非对称加解密

  1. 客户端先从服务器获取到证书,证书中包含公钥
  2. 客户端将证书进行校验
  3. 客户端生成一个对称密钥,用证书中的公钥进行加密,发送给服务器
  4. 服务器得到这个请求后用私钥进行解密,得到该密钥
  5. 客户端以后发出后续的请求,都使用这个对称密钥进行加密。
  6. 服务器收到这个密文也用这个密钥进行解密。

优势:

  • 混合加密解决了信息的机密性,防止数据被窃听
  • 摘要算法实现了数据的完成性,防止了数据被篡改
  • 数字证书提供了身份验证,防止了被冒充风险

CA证书

为了表示server发过来的公钥是可信的,所以需要对公钥进行验证

  • server发送CA证书给client

    里面包括两端内容:

    • 公钥A和server信息组成的大数据段C(域名,运行商信息等)
    • 数字签名:
      • 对数据C进行hash变成hash值T,在用私钥BB(另一对公钥AA和私钥BB)对T进行加密变成数字签名
  • Client收到CA证书后用浏览器内置的公钥AA对数字签名进行解密和反Hash,得到结果后与数据段C进行匹配

    • 匹配则数据段C里的公钥A可信任
    • 不匹配则数据段C里的公钥A不可信任

https的安全协议,如何识别新建第三方的电子证书

是一种通过计算机网络进行安全通信的传输协议。HTTPS经由HTTP进行通信,但利用SSL/TLS来加密数据包。是一种通过计算机网络进行安全通信的传输协议。HTTPS经由HTTP进行通信,但利用TLS来加密数据包。

针对TCP3次握手怎么攻击

SYN-洪水攻击

假设一个用户向服务器发送了SYN报文后突然死机或掉线,那么服务器在发出SYN+ACK应答报文后是无法收到客户端的ACK报文的(第三次握手无法完成),
这种情况下服务器端一般会重试(再次发送SYN+ACK给客户端)并等待一段时间后丢弃这个未完成的连接。 这段时间的长度我们称为SYN Timeout,一般来说这个时间是分钟的数量级(大约为30秒-2分钟)。一个用户出现异常导致服务器的一个线程等待1分钟并不是什么很大的问题,
但如果有一个恶意的攻击者大量模拟这种情况,服务器端将为了维护一个非常大的半连接列表而消耗非常多的资源----数以万计的半连接,即使是简单的保存并遍历也会消耗非常多的CPU时间和内存,何况还要不断对这个列表中的IP进行SYN+ACK的重试。
实际上如果服务器的TCP/IP栈不够强大,最后的结果往往是堆栈溢出崩溃---即使服务器端的系统足够强大,服务器端也将忙于处理攻击者伪造的TCP连接请求而无暇理睬客户的正常请求(毕竟客户端的正常请求比率非常之小)。 此时从正常客户的角度看来,服务器失去响应, 这种情况我们称作:服务器端受到了SYN Flood攻击(SYN洪水攻击)。

使用SYN cookie可以有效抵御泛洪攻击:

服务器在第二次握手时不会为第一次握手的SYN创建半开连接,而是生成一个cookie一起发送给客户端,只有客户端在第三次握手发送ACK报文并且验证cookie成功服务器才会创建TCP连接,分配资源。

DDos攻击原理

网络层DDos攻击
(1)SYN flood攻击

SYN flood攻击主要利用了TCP三次握手过程中的bug,我们知道TCP三次握手过程是要建立连接的双方发送SYN,SYN+ACK,ACK数据包,而当攻击方随意构造源ip去发送SYN包时,服务器返回的SYN+ACK就不能得到应答(因为ip是随意构造的),此时服务器就会尝试重新发送,并且会有至少30s的等待时间,导致资源饱和服务不可用,此攻击属于慢型dos攻击。

(2)UDP flood攻击

由于udp是一种无连接的协议,因此攻击者可以伪造大量的源IP地址去发送udp包,此种攻击属于大流量攻击。正常应用情况下,UDP包双向流量会基本相等,因此在消耗对方资源的时候也在消耗自己的资源。

(3)ICMP flood攻击

此攻击属于大流量攻击,其原理就是不断发送不正常的ICMP包(所谓不正常就是ICMP包内容很大),导致目标带宽被占用,但其本身资源也会被消耗。并且目前很多服务器都是禁ping的(在防火墙在可以屏蔽icmp包),因此这种方式已经落伍。

应用层DDos攻击
(1)CC攻击(Challenge Collapasar

CC攻击的原理,就是针对消耗资源比较大的页面不断发起不正常的请求,导致资源耗尽。因此在发送CC攻击前,我们需要寻找加载比较慢,消耗资源比较多的网页,比如需要查询数据库的页面、读写硬盘文件的等。通过cc攻击,使用爬虫对某些加载需要消耗大量资源的页面发起http请求。

(2)HTTP POST DOS

原理是在发送HTTP POST包时,指定一个非常大的Content-Length值,然后以极低的速度发包,保持连接不断,导致服务饱和不可用。

TCP的传输过程是怎么样的?怎么确保有序?

主机每次发送数据时,TCP就给每个数据包分配一个序列号并且在一个特定的时间内等待接收主机对分配的这个序列号进行确认,如果发送主机在一个特定时间内没有收到接收主机的确认,则发送主机会重传此数据包。接收主机利用序列号对接收的数据进行确认,以便检测对方发送的数据是否有丢失或者乱序等,接收主机一旦收到已经顺序化的数据,它就将这些数据按正确的顺序重组成数据流并传递到高层进行处理。

具体步骤如下:
(1)为了保证数据包的可靠传递,发送方必须把已发送的数据包保留在缓冲区;
(2)并为每个已发送的数据包启动一个超时定时器;
(3)如在定时器超时之前收到了对方发来的应答信息(可能是对本包的应答,也可以是对本包后续包的应答),则释放该数据包占用的缓冲区;
(4)否则,重传该数据包,直到收到应答或重传次数超过规定的最大次数为止。
(5)接收方收到数据包后,先进行CRC校验,如果正确则把数据交给上层协议,然后给发送方发送一个累计应答包,表明该数据已收到,如果接收方正好也有数据要发给发送方,应答包也可方在数据包中捎带过去。

http header里有什么

参数 说明 示例
Accept-Ranges 表明服务器是否支持指定范围请求及哪种类型的分段请求 Accept-Ranges: bytes
Age 从原始服务器到代理缓存形成的估算时间(以秒计,非负) Age: 12
Allow 对某网络资源的有效的请求行为,不允许则返回405 Allow: GET, HEAD
Cache-Control 告诉所有的缓存机制是否可以缓存及哪种类型 Cache-Control: no-cache
Content-Encoding web服务器支持的返回内容压缩编码类型。 Content-Encoding: gzip
Content-Language 响应体的语言 Content-Language: en,zh
Content-Length 响应体的长度 Content-Length: 348
Content-Location 请求资源可替代的备用的另一地址 Content-Location: /index.htm
Content-MD5 返回资源的MD5校验值 Content-MD5: Q2hlY2sgSW50ZWdyaXR5IQ==
Content-Range 在整个返回体中本部分的字节位置 Content-Range: bytes 21010-47021/47022
Content-Type 返回内容的MIME类型 Content-Type: text/html; charset=utf-8
Date 原始服务器消息发出的时间 Date: Tue, 15 Nov 2010 08:12:31 GMT
ETag 请求变量的实体标签的当前值 ETag: “737060cd8c284d8af7ad3082f209582d”
Expires 响应过期的日期和时间 Expires: Thu, 01 Dec 2010 16:00:00 GMT
Last-Modified 请求资源的最后修改时间 Last-Modified: Tue, 15 Nov 2010 12:45:26 GMT
Location 用来重定向接收方到非请求URL的位置来完成请求或标识新的资源 Location: http://www.zcmhi.com/archives/94.html
Pragma 包括实现特定的指令,它可应用到响应链上的任何接收方 Pragma: no-cache
Proxy-Authenticate 它指出认证方案和可应用到代理的该URL上的参数 Proxy-Authenticate: Basic
refresh 应用于重定向或一个新的资源被创造,在5秒之后重定向(由网景提出,被大部分浏览器支持) Refresh: 5; url=                 http://www.zcmhi.com/archives/94.html
Retry-After 如果实体暂时不可取,通知客户端在指定时间之后再次尝试 Retry-After: 120
Server web服务器软件名称 Server: Apache/1.3.27 (Unix) (Red-Hat/Linux)
Set-Cookie 设置Http Cookie Set-Cookie: UserID=JohnDoe; Max-Age=3600; Version=1
Trailer 指出头域在分块传输编码的尾部存在 Trailer: Max-Forwards
Transfer-Encoding 文件传输编码 Transfer-Encoding:chunked
Vary 告诉下游代理是使用缓存响应还是从原始服务器请求 Vary: *
Via 告知代理客户端响应是通过哪里发送的 Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1)
Warning 警告实体可能存在的问题 Warning: 199 Miscellaneous warning
WWW-Authenticate 表明客户端请求实体应该使用的授权方案 WWW-Authenticate: Basic
Date 请求发送的日期和时间 Date: Tue, 15 Nov 2010 08:12:31 GMT
Content-Type 请求的与实体对应的MIME信息 Content-Type: application/x-www-form-urlencoded
Expect 请求的特定的服务器行为 Expect: 100-continue
From 发出请求的用户的Email From: user@email.com
Host 指定请求的服务器的域名和端口号 Host: www.zcmhi.com
If-Match 只有请求内容与实体相匹配才有效 If-Match: “737060cd8c284d8af7ad3082f209582d”
If-Modified-Since 如果请求的部分在指定时间之后被修改则请求成功,未被修改则返回304代码 If-Modified-Since: Sat, 29 Oct 2010 19:43:31 GMT
If-None-Match 如果内容未改变返回304代码,参数为服务器先前发送的Etag,与服务器回应的Etag比较判断是否改变 If-None-Match: “737060cd8c284d8af7ad3082f209582d”
If-Range 如果实体未改变,服务器发送客户端丢失的部分,否则发送整个实体。参数也为Etag If-Range: “737060cd8c284d8af7ad3082f209582d”
If-Unmodified-Since 只在实体在指定时间之后未被修改才请求成功 If-Unmodified-Since: Sat, 29 Oct 2010 19:43:31 GMT
Max-Forwards 限制信息通过代理和网关传送的时间 Max-Forwards: 10
Pragma 用来包含实现特定的指令 Pragma: no-cache
Proxy-Authorization 连接到代理的授权证书 Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Range 只请求实体的一部分,指定范围 Range: bytes=500-999
Referer 先前网页的地址,当前请求网页紧随其后,即来路 Referer: http://www.zcmhi.com/archives/71.html
TE 客户端愿意接受的传输编码,并通知服务器接受接受尾加头信息 TE: trailers,deflate;q=0.5
Upgrade 向服务器指定某种传输协议以便服务器进行转换(如果支持) Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11
User-Agent User-Agent的内容包含发出请求的用户信息 User-Agent: Mozilla/5.0 (Linux; X11)
Via 通知中间网关或代理服务器地址,通信协议 Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1)
Warning 关于消息实体的警告信息 Warn: 199 Miscellaneous warning
Accept 指定客户端能够接收的内容类型 Accept: text/plain, text/html
Accept-Charset 浏览器可以接受的字符编码集。 Accept-Charset: iso-8859-5
Accept-Encoding 指定浏览器可以支持的web服务器返回内容压缩编码类型。 Accept-Encoding: compress, gzip
Accept-Language 浏览器可接受的语言 Accept-Language: en,zh
Accept-Ranges 可以请求网页实体的一个或者多个子范围字段 Accept-Ranges: bytes
Authorization HTTP授权的授权证书 Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Cache-Control 指定请求和响应遵循的缓存机制 Cache-Control: no-cache
Connection 表示是否需要持久连接。(HTTP 1.1默认进行持久连接) Connection: close
Cookie HTTP请求发送时,会把保存在该请求域名下的所有cookie值一起发送给web服务器。 Cookie: $Version=1; Skin=new;
Content-Length 请求的内容长度 Content-Length: 348

服务器怎么知道body中有什么

在TCP/IP协议栈里,传输数据基本上都是"header+body"的格式。但是TCP、UDP因为是传输层的协议,它们不会关心body数据是什么,只是要把数据发送到对方就算是完成了任务。而HTTP协议则不同,它是应用层协议,数据到达之后工作只能说是完成了一半,还必须告诉上层应用这是什么数据才行,否则上层应用就会“不知所措”。

早在HTTP协议诞生之前就已经有了针对这种问题的解决方案,不过它是用在电子邮件系统里的,让电子邮件可以发送ASCII码以外的任意数据,方案的名字叫做“多用途互联网邮件扩展”(Multipurpose Internet MailExtensions),简称为 MIME。

MIME是一个很大的标准规范,但HTTP只取了其中的一部分, 用来标记body的数据类型,这就是“MIME type”。

  • 数据类型表示实体数据的内容是什么,使用的是 MIME type,相关的头字段是 Accept 和 Content-Type;
  • 数据编码表示实体数据的压缩方式,相关的头字段是Accept-Encoding 和 Content-Encoding;
  • 语言类型表示实体数据的自然语言,相关的头字段是Accept-Language 和 Content-Language;
  • 字符集表示实体数据的编码方式,相关的头字段是Accept-Charset 和 Content-Type;
  • 客户端需要在请求头里使用 Accept 等头字段与服务器进行“内容协商”,要求服务器返回最合适的数据;
  • Accept 等头字段可以用“,”顺序列出多个可能的选项,还可以用“;q=”参数来精确指定权重。

http2.0新特性 

二进制分帧

HTTP 2.0最大的特点:不会改动HTTP 的语义,HTTP 方法、状态码、URI 及首部字段,等等这些核心概念上一如往常,却能致力于突破上一代标准的性能限制,改进传输性能,实现低延迟和高吞吐量。而之所以叫2.0,是在于新增的二进制分帧层。

在HTTP/1.x中,通过文本形式传输数据
而在HTTP/2.0中,所有数据都会被分割,并在应用层和传输层之间增加一个二进制分帧层
首部信息被封装到Header帧,请求主体被封装到Data帧,采用二进制编码

多路复用

在HTTP/2.0中,每个请求/响应都可以看作一个流(stream),并给每个stream分配id
一个TCP连接上可以有多个stream,stream中的帧都是乱序
到对端后 再根据帧的stream_id重新组装
这样可以避免队首阻塞问题,极大地提高传输性能

首部压缩

HTTP 1.x首部是没有压缩的,Gzip只会对请求体进行压缩

现在HTTP 2.0 提供了首部压缩方案。现在SPDY和HTTP 2.0都支持首部压缩,前者使用的是DEFLATE算法,而后者使用专门设计的HPACK算法。
并在通信两端维护索引表,记录出现过的header,对于相同的header,不必多次发送

流量控制

HTTP 2.0 “流” 的流量控制最终的目标是在不改变协议的情况之下允许采用多种流量控制算法。

流量控制特点:

  • 流量基于HTTP连接的每一跳进行,非端到端控制
  • 流量基于窗口更新帧进行,接收方可广播准备接收字节数甚至对整个连接要接收的字节数
  • 流量控制有方向性,接收方可以根据自身情况进行控制窗口大小
  • 流量控制可以由接收方禁用,包括个别流和整个连接
  • 只有DATA帧服从流量控制,其他类型帧不会消耗控制窗口的空间

请求优先级

客户端可以通过在打开流的HEADERS帧中包含优先次序信息来为一个新流指定优先级。在其它任意时间,可以使用PRIORITY帧来改变流的优先级。每个流都可以带有一个31bit的优先值:0表示最高优先级;2的31次方-1表示最低优先级。

客户端明确指定优先级,服务端可以根据这个优先级作为交互数据的依据

服务器推送

服务器可以在客户端某个请求后,主动推送其他资源

服务器推送工作过程:

  • PUSH_PROMISE帧是服务端有意向客户端推送资源
  • PUSH_PROMISE帧只包含预推送资源的首部。如果客户端对此帧没有意见,服务端就会发送DATA帧响应。假如客户端缓存了可以拒绝推送。
  • 服务器遵守同源策略,不会随意推送第三方资源。

那么服务器怎么知道要给客户端推送什么资源呢?

location / {
      root   /usr/share/nginx/html;
      index  index.html index.htm;
      http2_push /style.css;
      http2_push /example.png;
 }

这是Nginx的实现方法,意思是当用户请求 / 路径时返回style.css和example.png文件。服务器推送可以减轻数据传送冗余步骤,加快页面响应速度,提升了用户体验。

HTTP1.X也有connect:keep-alive,怎么就不能实现服务端推送了?

HTTP/1.1协议里没有包含server push功能,都是一去(request)一回(response),或者多去多回(pipelining)。所以后续的HTTP协议,比如SPDY,HTTP/2.0,都增加了主动push。

爬虫中的限制和解决策略

1、UserAgent

  UserAgent的设置能使服务器能够识别客户使用的操作系统及版本、CPU 类型、浏览器及版本等信息。对于一些网站来说,它会检查我们发送的请求中所携带的UserAgent字段,如果非浏览器,就会被识别为爬虫,一旦被识别出来, 我们的爬虫也就无法正常爬取数据了。

  解决方法: 收集常见的useragent作为配置文件,每次访问的时候取出一个作为头部发送请求,需要注意的是同一个useragent如果访问频率太高也有可能被识别出来而被禁止,因此可以设置随机选取的策略,每一次访问都随机选取一个。

2、IP限制

  IP限制在反爬虫中是非常常见的,一般来讲都会有这个限制。

  解决方法:基于IP的反爬限制我们可以通过自己取搭建一个IP池,所谓IP池就是一个拥有很多IP的容器,这个容器可以用一个队列来实现或这其他数据结构。

3、验证码或模拟登陆

  通过验证码来进行反爬取措施是比较常用的方法。

  解决方法:验证码识别可以采用一些简单的处理:二值化、中值滤波去噪、分割、紧缩重排(让高矮统一)、字库特征匹配识别。

4、Ajax动态加载

  Ajax动态加载的原理就是当访问一个URL时,会先加载网页源代码,然后会在浏览器中执行Javascript代码,这些代码会加载很多东西,这些请求都属于AJAX请求,通过这些请求会生成很多的数据,然后再将这些数据传输到网页中。所以对这些请求,你直接访问URL是没有数据的。

  解决方法:对于使用动态加载的数据,我们只能通过调试工具或者抓包工具去分析Ajax请求的过程,然后去模拟这个请求发送来获取数据,一般我们获取到的数据都是json的数据格式,我们只需要解析json字符串就可以。

5、cookies限制

  对于某些网站会要求登录后才能访问,并且会对同一个账号进行访问的速度进行限制,例如同一个账号下,单位时间内超过某个固定的阈值就会进行限制。

  解决方法:我们可以通过模拟登录然后维持一个会话去发送请求,但是当访问数据较多时,可以研究服务器对账号进行限制的规律。还有一种方式就是搭建一个cookies池,动态得获取cookies,然后携带这些cookies去访问。

6、js加密

  这种方式常见于小程序或者APP的数据爬取,一般在post请求中较多。

  解决方法:对于这种没有别的办法,只能分析js代码,看看它是如何构造这段字符串的,然后通过Python中的库去模拟js构造的过程,然后发送请求。

ping命令是什么协议?

Ping使用ICMP协议(Internet消息控制协议)

ICMP请求报文和ICMP回答报文。

Ping 是 ICMP 的一个重要应用,主要用来测试两台主机之间的连通性。 Ping 的原理是通过向目的主机发送 ICMP Echo 请求报文,目的主机收到之后会发送 Echo 回答报文。Ping 会根据时间和成功响应的次数估算出数据包往返时间以及丢包率。