网站如何防止攻击,如何建立网上授课平台,企业网站 联系我们,怎么做免流网站前言
1.本系列面试八股文的题目及答案均来自于网络平台的内容整理#xff0c;对其进行了归类整理#xff0c;在格式和内容上或许会存在一定错误#xff0c;大家自行理解。内容涵盖部分若有侵权部分#xff0c;请后台联系#xff0c;及时删除。
2.本系列发布内容分为12篇…前言
1.本系列面试八股文的题目及答案均来自于网络平台的内容整理对其进行了归类整理在格式和内容上或许会存在一定错误大家自行理解。内容涵盖部分若有侵权部分请后台联系及时删除。
2.本系列发布内容分为12篇 分别是
c/c语言 数据结构与算法 GDB 设计模式 操作系统 系统编程 网络原理 网络编程 mysql redis 服务器 RPG 本文为第七篇后续会陆续更新。 共计200道八股文。
3.本系列的200道为整理的八股文系列的一小部分。完整整理完的八股文面试题共计1000道100W字左右体量太大故此处放至百度云盘链接 https://pan.baidu.com/s/1IOxQs0ifbSPGgxK7Yz7BtQ?pwdzl1i
提取码zl1i 需要的同学自取即可。
4.八股文对于面试的同学来说仅作为参考使用不能作为面试上岸的唯一准备还是要结合自身的技术能力和项目同步发育。
最后祝各位同学都能拿到自己满意的offer成功上岸 ————————————————
七、网络原理
01.为什么握手是三次而挥手需要四次
TCP的三次握手是为了建立可靠的连接。具体来说客户端发送一个SYN包到服务器表示自己想要建立连接。服务器收到这个包后回复一个SYNACK包表示自己已经收到请求并且同意建立连接。最后客户端再发送一个ACK包表示自己也已经收到了服务器的回复并且同意建立连接。
这里之所以要进行三次握手是因为TCP是面向连接的协议需要确保双方都正确地接收到了对方的请求才能建立可靠的连接。通过三次握手的方式可以确保连接的双方都认可了对方的身份和可用性从而避免了因为网络延迟等原因导致连接建立失败的情况。
四次挥手是为了关闭连接。具体来说当客户端想要关闭连接时发送一个FIN包到服务器表示自己不再发送数据了。服务器收到这个包后回复一个ACK包表示自己已经收到了请求。但是服务器可能还没有发送完自己的数据所以服务器在发送完数据后会再次发送一个FIN包表示自己也不再发送数据了。客户端收到这个包后回复一个ACK包表示自己已经收到了服务器的请求同时也准备关闭连接了。
四次挥手之所以要比三次握手多一次是因为在关闭连接时双方都需要确认自己的数据已经全部传输完毕才能安全地关闭连接。另外因为TCP具有可靠传输的特点所以在关闭连接时需要先停止数据的发送等待对方完成传输后再关闭连接从而避免数据丢失或被截断。
02.tcp和udp的原理、区别、应用场景
1.TCP
TCP 是面向连接的、可靠的、基于字节流的传输层通信协议。
面向连接一定是「一对一」才能连接不能像 UDP 协议可以一个主机同时向多个主机发送消息也就是一对多是无法做到的可靠的无论的网络链路中出现了怎样的链路变化TCP 都可以保证一个报文一定能够到达接收端字节流用户消息通过 TCP 协议传输时消息可能会被操作系统「分组」成多个的 TCP 报文如果接收方的程序如果不知道「消息的边界」是无法读出一个有效的用户消息的。并且 TCP 报文是「有序的」当「前一个」TCP 报文没有收到的时候即使它先收到了后面的 TCP 报文那么也不能扔给应用层去处理同时对「重复」的 TCP 报文会自动丢弃。
2.UDP
用户数据报协议UDPUDP用户数据报协议是一个简单的面向数据报的传输层协议。
提供的是非面向连接的、不可靠的数据流传输。
UDP不提供可靠性也不提供报文到达确认、排序以及流量控制等功能。它只是把应用程序传给IP层的数据报发送出去但是并不能保证它们能到达目的地。因此报文可能会丢失、重复以及乱序等。但由于UDP在传输数据报前不用在客户和服务器之间建立一个连接且没有超时重发等机制故而传输速度很快。
3.TCP优缺点
优点可靠、稳定
TCP的可靠体现在TCP在传输数据之前会有三次握手来建立连接而且在数据传递时有确认、窗口、重传、拥塞控制机制在数据传完之后还会断开连接用来节约系统资源。
缺点慢效率低占用系统资源高易被攻击
在传递数据之前要先建立连接这会消耗时间而且在数据传递时确认机制、重传机制、拥塞机制等都会消耗大量时间而且要在每台设备上维护所有的传输连接。然而每个链接都会占用系统的CPU、内存等硬件资源。因为TCP有确认机制、三次握手机制这些也导致TCP容易被利用实现DOS、DDOS、CC等攻击。
4.UDP优缺点
优点快
比TCP稍安全UDP没有TCP拥有的各种机制是一个无状态的传输协议所以传递数据非常快没有TCP的这些机制被攻击利用的机制就少一些但是也无法避免被攻击。
缺点不可靠不稳定
因为没有TCP的那些机制UDP在传输数据时如果网络质量不好就会很容易丢包造成数据的缺失。
5.区别
TCP和UDP有如下区别
连接TCP面向连接的传输层协议即传输数据之前必须先建立好连接UDP无连接。服务对象TCP点对点的两点间服务即一条TCP连接只能有两个端点UDP支持一对一一对多多对一多对多的交互通信。可靠性TCP可靠交付无差错不丢失不重复按序到达UDP尽最大努力交付不保证可靠交付。拥塞控制/流量控制TCP有拥塞控制和流量控制保证数据传输的安全性UDP没有拥塞控制网络拥 塞不会影响源主机的发送效率。报文长度TCP动态报文长度即TCP报文长度是根据接收方的窗口大小和当前网络拥塞情况决定的UDP面向报文不合并不拆分保留上面传下来报文的边界。首部开销TCP首部开销大首部20个字节UDP首部开销小8字节源端口目的端口数据长度校验和。适用场景由特性决定数据完整性需让位于通信实时性则应该选用TCP 协议如文件传输、重要状态的更新等反之保证数据完整性则使用 UDP 协议如视频传输、实时通信等。
6.适用场景网络稳定性要求
6.1 TCP
TCP当对网络通讯质量有要求时比如HTTP、HTTPS、FTP等传输文件的协议 POP、SMTP等邮件传输的协议
对可靠连接有要求时比如付费、加密数据等等方向都需要依靠TCP
6.2 UDP
UDP对网络通讯质量要求不高时要求网络通讯速度要快的场景。
所以主要使用在以下场景
包总量较小的通信DNS、SNMP视频、音频等多媒体通信即时通信QQ就是使用的UDP协议。广播通信
所以TCP对网络稳定性要求高而UDP相对弱一些。
03.TCP慢启动拥塞控制实现
TCP的拥塞控制
一、前言什么是拥塞什么是拥塞控制
拥塞随着网络中的主机增加其发送速率并使网络变得十分拥挤此时会经常发生丢包现象导致网络的传输效率急剧降低。分组的超时重传通常被作为网络拥塞的标志。如果不对网络拥塞进行控制整个网络的吞吐量将随着输入负荷的增大而下降降低网络的传输效率如下图 二、TCP的4种拥塞控制算法(慢开始、拥塞避免、快重传、快恢复)
为了便于讨论做一下假设
数据是单方向传送的另一个方向只传输确认接收方的总是有足够大的缓冲区因此发送方的发送窗口仅由网络的拥塞程度决定事实上发送窗口的大小由拥塞窗口和接收方的接收窗口大小共同控制也即发送窗口 min[接收窗口, 拥塞窗口]以最大报文段MSS的个数作为讨论单位而不是以字节为单位
发送方维护一个叫做拥塞窗口cwnd(congestion window)的状态变量其值取决于网络的拥塞状况动态变化
拥塞窗户的维护原则只要网络没有出现拥塞cwnd就增大一些但只要网络出现拥塞拥塞窗口就减小一些以分组发生超时重传作为发生网络拥塞的依据
TCP还维护一个慢开始门限ssthresh状态变量
当cwnd ssthresh时使用慢开始算法当cwnd ssthresh时使用拥塞避免算法当cwnd ssthresh时既可以使用慢开始算法也可以使用拥塞避免算法
当发生数据正常丢包但又不是网络拥塞时使用快重传算法和快恢复算法
如何判断是发生了正常丢包而不是网络拥塞呢当发送方连续接收到3次重复确认时说明这网络不拥塞只是正常丢包了
① 慢启动(慢开始) 传输轮次指把发送窗口内可以发送的数据全部发送并接收到最后一个TCP报文的确认报文这样一个来回 通常在一条TCP连接开始时cwnd被设置为1个MSS最大报文段也即cwnd1该阶段每当TCP发送方将发送窗口的数据发送完并顺利接收到所有的确认后就会将拥塞窗口大小翻倍也即慢启动阶段cwnd以指数形式增长如上图所示注意这里忽略了接收窗口的影响上文也提到了。拥塞窗口会一直增长直到到达慢开始门限ssthresh开始执行拥塞避免算法
② 拥塞避免
该阶段的拥塞窗口变为线性增长每次cwnd1也即每次增加一个MSS 随着拥塞窗口的增加发送速率不断提高当TCP遇到分组超时重传时即认为发生了网络拥塞
此时将更新ssthresh的值为当前拥塞窗口的一半上图中是更新为24的一半即12更新cwnd的值为1然后继续执行慢启动—拥塞避免如上图所示
如果TCP发送方接收到连续的3个重复确认则认为是正常的网络包丢失而不是网络拥塞造成的这正是快重传算法的功劳
重传丢失的分组执行快恢复算法
③ 快重传
所谓的快重传算法就是让发送方尽快重传而不是等待超时重传计时器超时再重传
要求接收方不要等待自己发送数据时才捎带确认而是要立即发送确认即使是失序的报文段也要立即发送对已收到的报文段的重复确认发送方一旦收到3个连续的重复确认就将相应的报文段立即重传而不是等待该报文的重传计时器超时再重传
如下图所示 ④ 快恢复
如果发送方收到了3个重复确认就执行快恢复算法
将慢开始门限sstresh和拥塞窗口cwnd都设置为当前拥塞窗口的一半然后执行拥塞避免算法
三、一个糅合了4种拥塞控制算法的例子 最初cwnd1ssthresh16执行慢开始算法cwnd大小指数增长cwnd到达慢开始门限ssthresh后转而执行拥塞避免算法cwnd线性加一增长随着发送速率的增加若发生超时重传则将慢开始门限ssthresh减小为当前拥塞窗口的一半、再将拥塞窗口cwnd设置为1然后执行慢开始-–拥塞避免重复1、2若发送方收到3个重复确认则表示分组丢失发送方立刻重传相应分组然后执行快恢复算法将慢开始门限ssthresh和拥塞窗口cwnd重新设置为当前拥塞窗口的一半然后执行拥塞避免算法
04.HTTP是在OSI模型的哪一层
HTTP超文本传输协议是应用层协议它是在 OSI 模型的最高层即第七层——应用层。HTTP 通过互联网来传输数据和信息主要用于 Web 浏览器和 Web 服务器之间的通信以及客户端与服务器之间的文件传输、查询和请求响应等操作。
05.HTTPS用到的是对称加密还是非对称加密分别体现在哪里
一、对称加密与非对称加密
HTTPS 的安全性是由 TLS 来保证的。
加密可以分为两大类对称加密和非对称加密。
1.1 对称加密
对称加密的方法是双方使用同一个秘钥对数据进行加密和解密。但是对称加密的存在一个问题就是如何保证秘钥传输的安全性因为秘钥还是会通过网络传输的一旦秘钥被其他人获取到那么整个加密过程就毫无作用了。 这就要用到非对称加密的方法。速度要比非对称加密快。
1.2 非对称加密
非对称加密的方法是我们拥有两个秘钥一个是公钥一个是私钥。公钥是公开的私钥是保密的。用私钥加密的数据只有对应的公钥才能解密用公钥加密的数据只有对应的私钥才能解密。我们可以将公钥公布出去任何想和我们通信的客户 都可以使用我们提供的公钥对数据进行加密这样我们就可以使用私钥进行解密这样就能保证数据的安全了。但是非对称加密有一个缺点就是加密的过程很慢因此如果每次通信都使用非对称加密的方式的话反而会造成等待时间过长的问题。
二、混合加密
对称加密和非对称加密搭配使用。
基于以上两点原因最终选择了一个更加完美的方案那就是在传输数据阶段依然使用对称加密但是对称加密的密钥我们采用非对称加密来传输。
https使用混合加密并且还要配合数字证书来实现安全性。 从图中可以看出改造后的流程是这样的
首先浏览器向服务器发送对称加密套件列表、非对称加密套件列表和随机数 client-random服务器保存随机数 client-random选择对称加密和非对称加密的套件然后生成随机数 service-random向浏览器发送选择的加密套件、service-random 和公钥浏览器保存公钥并利用 client-random 和 service-random 计算出来 pre-master然后利用公钥对 pre-master 加密并向服务器发送加密后的数据最后服务器拿出自己的私钥解密出 pre-master 数据并返回确认消息。
到此为止服务器和浏览器就有了共同的 client-random、service-random 和 pre-master然后服务器和浏览器会使用这三组随机数生成对称密钥因为服务器和浏览器使用同一套方法来生成密钥所以最终生成的密钥也是相同的。
有了对称加密的密钥之后双方就可以使用对称加密的方式来传输数据了。
需要特别注意的一点pre-master 是经过公钥加密之后传输的所以黑客无法获取到 pre-master这样黑客就无法生成密钥也就保证了黑客无法破解传输过程中的数据了 注什么是加密套件 加密套件CipherList是指在ssl通信中服务器和客户端所使用的加密算法的组合。在ssl握手初期客户端将自身支持的加密套件列表发送给服务器在握手阶段服务器根据自己的配置从中尽可能的选出一个套件作为之后所要使用的加密方式。 其实就是服务器选择一个双方要使用的加密方法。 三、添加数字证书 混合加密
对称加密和非对称加密以及两者结合起来的混合加密实现了机密性。 但仅有机密性离安全还差的很远。
黑客虽然拿不到会话密钥无法破解密文但可以通过窃听收集到足够多的密文再尝试着修改、重组后发给网站。因为没有完整性保证服务器只能“照单全收”然后他就可以通过服务器的响应获取进一步的线索最终就会破解出明文。
另外黑客也可以伪造身份发布公钥。如果你拿到了假的公钥混合加密就完全失效了。你以为自己是在和“某宝”通信实际上网线的另一端却是黑客银行卡号、密码等敏感信息就在“安全”的通信过程中被窃取了。
所以在机密性的基础上还必须加上完整性、身份认证等特性才能实现真正的安全。
3.1 https的真正请求流程
https使用混合加密并且还要配合数字证书来实现安全性。
客户端向服务器发起请求请求中包含使用的TLS版本号、生成的一个随机数、以及客户端支持的加密方法。服务器端接收到请求后确认双方使用的加密方法和TLS版本号、并给出服务器的证书、以及一个服务器生成的随机数。客户端确认服务器证书有效后生成一个新的随机数并使用数字证书中解密拿到的服务器公钥加密这个随机数然后发给服务器。服务器使用自己的私钥来解密客户端发送过来的随机数。这样服务器就拿到了第三个随机数。而且只有客户端和服务器端知道这第三个随机数因为第三个随机数是通过加密传输的。客户端和服务器端根据约定的加密方法使用前面的三个随机数生成会话秘钥以后的对话过程都使用这个秘钥即会话秘钥来加密信息。以后客户端和服务器端都使用这个会话秘钥来加密。 四、数字证书
服务器获取证书 首先服务器先用Hash算法将自己的公钥和其他信息(例如认证时长服务器域名…)进行加密生成一个信息摘要传递给认证机构并且认证机构也会有自己的公钥和私钥并且认证机构会将自己的公钥给了浏览器。然后认证机构会用自己的私钥对已经拿到的浏览器摘要进行加密生成签名签名和信息摘要合在一起称为数字证书认证机构生成的签名是证书的关键有了这个认证机构的签名证书就合法了。然后再把这个证书传递给服务器服务器会保存自己的证书服务器并且也会把证书传递给浏览器。浏览器用认证机构传给自己的公钥对证书进行解密拿到摘要A并读取证书中相关的明文信息采用 CA 签名时相同的 Hash 函数来计算并得到摘要B对比信息摘要 A 和信息摘要 B如果一致则可以确认证书是合法的同时在摘要A中也拿到了服务器的公钥。
摘要 给计算机一篇文章计算机用摘要算法主要是哈希类算法生成一个字符串如果文章内容改变哪怕是一个字一个标点符号摘要也会完全改变。和完全加密一篇文章相比摘要的体积很小因此非常有利于存储和传输。
通常对于一个给定的摘要算法无论你的文章多大有多少字节最终生成摘要的字节数是固定的。
摘要是对原文的证明从原文到摘要是一个不可逆的过程。
通过原文可以计算出摘要一旦原文发生变化哪怕是一个标点符号摘要也会发生变化。而已知一个摘要想要反推出原文几乎是不可能的。因为摘要和原文并不是一对一的关系是多个原文对应一个摘要。而且想要找到两个摘要碰撞的原文是非常困难的发生概率相当于买彩票中大奖 。而且就算黑客找到了碰撞的原文也未必可以起到作用。
签名 如果张三将合同生成摘要再用自己的私钥加密摘要得到一个密文串那么这个串就是张三对合同的数字签名
06.http2和http1的区别
一、HTTP1和HTTP2的区别
1.新的二进制格式HTTP2采用二进制格式而HTTP1使用文本格式。
2.多路复用HTTP2是完全多复用的而非有序并阻塞的只需一个连接即可实现并行。HTTP1一个连接只能发送一个请求。
3.首部压缩HTTP1.x的header带有大量信息而且每次都要重复发送HTTP2.0使用encoder来减少需要传输的header大小通讯双方各自cache一份header fields表既避免了重复header的传输又减小了需要传输的大小。
4.服务器推送HTTP2在客户端请求资源的时候会把相关的资源一起发送给客户端而不需要客户端再次发起请求获取资源。
二、什么是HTTP2.0
HTTP/2超文本传输协议第2版最初命名为HTTP 2.0是HTTP协议的的第二个主要版本使用于万维网。HTTP/2是HTTP协议自1999年HTTP 1.1发布后的首个更新主要基于SPDY协议是Google开发的基于TCP的应用层协议用以最小化网络延迟提升网络速度优化用户的网络使用体验。
三、为什么需要头部压缩
HTTP协议是不带有状态的每次请求头部都会附上所有的信息而且很多的信息都是重复的这会浪费很多宽带也会影响速度所以HTTP2对头部进行了压缩一方面使用gzip或compress进行头部压缩另一方面客户端和服务器会同时维护同一张头信息表所有的字段都会存入这张表中生成一个索引号以后就不需要再发送同样的字段了只发送索引号提示了速度。
07.http1.0 / 1.1 / 2 / 3
1.HTTP1.0 HTTP/1.0是无状态、无连接的应用层协议。
无连接
无连接每次请求都要建立连接需要使用 keep-alive 参数建立长连接、HTTP1.1默认长连接keep-alive 无法复用连接每次发送请求都要进行TCP连接TCP的连接释放都比较费事会导致网络利用率低
队头阻塞
队头阻塞(head of line blocking)由于HTTP1.0规定下一个请求必须在前一个请求响应到达之前才能发送假设前一个请求响应一直不到达那么下一个请求就不发送后面的请求就阻塞了。 缓存
在HTTP1.0中主要使用header里的协商缓存 last-modified\if-modified-since强缓存 Expires来做为缓存判断的标准
If-Modified-Since Expires是RFC 2616HTTP/1.0协议中和网页缓存相关字段。用来控制缓存的失效日期。
Expires 字段声明了一个网页或 URL 地址不再被浏览器缓存的时间一旦超过了这个时间浏览器都应该联系原始服务器。RFC告诉我们“由于推断的失效时间也许会降低语义透明度应该被谨慎使用同时我们鼓励原始服务器尽可能提供确切的失效时间。”
其他问题
HOST域认为每个服务器绑定唯一一个IP地址因此在请求消息的URL中没有主机名HTTP1.0没有host域。而现在在一台服务器上可以存在多个虚拟主机并且它们共享一个IP地址。
HTTP1.0不支持断点续传功能每次都会传送全部的页面和数据。如果只需要部分数据就会浪费多余带宽 2.HTTP/1.1 特点
简单 HTTP 基本的报文格式就是 header body头部信息也是 key-value 简单文本的形式易于理解
灵活、易扩展 各类请求方法、URL、状态码等每个组成都没有固定死开发者可以自定义与扩充 HTTP在应用层其下层可以灵活变化https就是HTTP与TCP之间增加SSL/TSL安全传输协议
应用广泛、支持跨平台
优缺点
1.无状态 好处服务器不用额外资源记录减轻服务器负担提高CPU内存利用效率 坏处每次都要确认验证信息一般通过Cookie解决Cookie 通过在请求和响应报文中写入 Cookie 信息来控制客户端的状态。 2.明文传输 传输过程中信息可以抓包直接获取信息暴露、安全性差 3.不安全 通信使用明文传输、信息泄露 不验证通信双方身份、有可能进入伪装网站 无法证明报文完整性都导致不安全的问题 解决方式可以用 HTTPS 的方式解决也就是通过引入 SSL/TLS 层使得更安全。
长连接
为了解决早期HTTP/1.0每次都要建立连接导致通信效率低的性能问题因为HTTP基于TCP/IP协议 为了解决上述 TCP 连接问题HTTP/1.1 提出了长连接的通信方式也叫持久连接。这种方式的好处在于减少了 TCP 连接的重复建立和断开所造成的额外开销减轻了服务器端的负载。
持久连接的特点是只要任意一端没有明确提出断开连接则保持 TCP 连接状态。如果某个 HTTP 长连接超过一定时间没有任何数据交互服务端就会主动断开这个连接。
短连接和长连接对比 管道传输
因为HTTP/1.1 采用了长连接的方式这使得管道pipeline网络传输成为了可能。
即可在同一个 TCP 连接里面客户端可以发起多个请求只要第一个请求发出去了不必等其回来就可以发第二个请求出去可以减少整体的响应时间。 但是服务器必须按照接收请求的顺序发送对这些管道化请求的响应。
如果服务端在处理 A 请求时耗时比较长那么后续的请求的处理都会被阻塞住这称为「队头堵塞」。
所以HTTP/1.1 管道解决了请求的队头阻塞但是没有解决响应的队头阻塞。
注意实际上 HTTP/1.1 管道化技术不是默认开启而且浏览器基本都没有支持所以后面讨论HTTP/1.1 都是建立在没有使用管道化的前提。
3.HTTP/1.0 比较 HTTP/1.1
HTTP/1.1 相比 HTTP/1.0 提高了什么性能
使用长连接的方式改善了 HTTP/1.0 短连接造成的性能开销。支持管道pipeline网络传输只要第一个请求发出去了不必等其回来就可以发第二个请求出去可以减少整体的响应时间 HTTP协议层次结构图
现在主流浏览器大部分使用的都是HTTP/1.1协议也有部分支持HTTP/2.0绝大部分网站都升级为HTTPS更保证安全性 4.HTTP/2.0
详见该文章深入理解HTTP/2.0 HTTP/2.0协议是基于HTTPS的更加安全
相比与HTTP/1.1HTTP/2.0增加如下几点的重大优化
头部压缩
HTTP2.0会压缩Header部分如果同时多个请求其头部一样或相似那么协议会消除重复部分。 利用HPAK算法在客户端和服务器同时维护一张头信息表所有字段都会存入这个表生成一个索引号就不用重复发送同样字段了只发送索引号减少数据量提高速度
二进制格式
HTTP/1.0和HTTP/1.1中报文都是纯文本的格式简单易读而在2.0中采用了二进制的格式 报头和数据体称为帧frame-》头信息帧Headers Frame和数据帧Data Frame 文本形式信息保存为一个一个字符占用空间多每个字符对应比特位多接受方还需要将报文转换为二进制而直接用二进制减少了传输数据量提高数据传输效率
1.0 2.0
数据以数据流stream的形式以字节单位发送数据包可以不按顺序发送
在 HTTP/2 中每个请求或响应的所有数据包称为一个数据流Stream。每个数据流都标记着一个独一无二的编号Stream ID 所有HTTP2.0通信都在一个TCP链接上完成这个链接可以承载任意流量的双向数据流。每个数据流以消息的形式发送而消息由一或多个帧组成。不同 Stream 的帧是可以乱序发送的因此可以并发不同的 Stream 因为每个帧的头部会携带 Stream ID 信息所以接收端可以通过 Stream ID 有序组装成 HTTP 消息
客户端还可以指定数据流的优先级。优先级高的请求服务器就先响应该请求
多路复用
HTTP2.0实现了真正的并行传输它能够在一个TCP上进行任意数量的HTTP请求由于其二进制分帧特性 HTTP/2 是可以在一个连接中并发多个请求或回应而不用按照顺序一一对应。
移除了 HTTP/1.1 中的串行请求不需要排队等待彻底解决「队头阻塞」问题降低了延迟大幅度提高了连接的利用率。
服务端推送
HTTP/2 还在一定程度上改善了传统的「请求 - 应答」工作模式服务端不再是被动地响应可以主动向客户端发送消息、推送额外的资源。
例如
TCP导致队头阻塞
因为TCP面向字节流传输而且保证传输可靠性和数据的完整性 只有TCP拿到完整连续的数据时内核才会将数据从缓冲区交给HTTP应用而只要前一个字节没有收到HTTP就无法从内核缓冲区中得到数据直到其到达所以在此过程仍然会导致队头阻塞
图中发送方发送了很多个 packet每个 packet 都有自己的序号你可以认为是 TCP 的序列号其中 packet 3 在网络中丢失了即使 packet 4-6 被接收方收到后由于内核中的 TCP 数据不是连续的于是接收方的应用层就无法从内核中读取到只有等到 packet 3 重传后接收方的应用层才可以从内核中读取到数据这就是 HTTP/2 的队头阻塞问题是在 TCP 层面发生的。 因此如果出现丢包就会触发TCP的超时重传这样后续缓冲队列中所有数据都得等丢了的重传
5.HTTP/3.0
仍在学习中…后续完善
基于Google的QUICHTTP3 背后的主要思想是放弃 TCP转而使用基于 UDP 的 QUIC 协议。
为了解决HTTP/2.0中TCP造成的队头阻塞问题HTTP/3.0直接放弃使用TCP将传输层协议改成UDP但是因为UDP是不可靠传输所以这就需要QUIC实现可靠机制
QUIC 也是需要三次握手来建立连接的主要目的是为了确定连接 ID。
可以学一下这篇文章QUIC详解用UDP实现可靠协议
在 UDP 报文头部与 HTTP 消息之间共有 3 层头部 QUIC特点
无队头阻塞
QUIC 协议也有类似 HTTP/2 Stream 与多路复用的概念也是可以在同一条连接上并发传输多个 StreamStream 可以认为就是一条 HTTP 请求。
QUIC 有自己的一套机制可以保证传输的可靠性的。当某个流发生丢包时只会阻塞这个流其他流不会受到影响因此不存在队头阻塞问题。这与 HTTP/2 不同HTTP/2 只要某个流中的数据包丢失了其他流也会因此受影响。
所以QUIC 连接上的多个 Stream 之间并没有依赖都是独立的某个流发生丢包了只会影响该流其他流不受影响。
连接建立
HTTP/3 在传输数据前虽然需要 QUIC 协议握手这个握手过程只需要 1 RTT握手的目的是为确认双方的「连接 ID」连接迁移就是基于连接 ID 实现的。 连接迁移
基于 TCP 传输协议的 HTTP 协议由于是通过四元组源 IP、源端口、目的 IP、目的端口确定一条 TCP 连接例如设备要连接wifiIP地址改变就必须要重新建立连接而建立连接包含TCP三次握手和TSL四次握手以及TCP慢启动所以会造成使用者卡顿的感觉
而QUIC通过连接ID标记自己客户端和服务器可以各自选择一组 ID 来标记自己因此即使移动设备的网络变化后导致 IP 地址变化了只要有上下文信息比如连接 ID、TLS 密钥等就可以“无缝”地复用原连接消除重连的成本没有丝毫卡顿感达到了连接迁移的功能。
其实 QUIC 是一个在 UDP 之上的伪 TCP TLS HTTP/2 的多路复用的协议。
08.get和post区别
GET 和 POST 是 HTTP 请求中最常用的两种请求方法在日常开发的 RESTful 接口中都能看到它们的身影。而它们之间的区别也是一道常见且经典的面试题所以我们本文就来详细的聊聊。 HTTP 协议定义的方法类型总共有以下 10 种
PS目前大部分的网站使用的都是 HTTP 1.1 的协议。
但在日常开发中使用频率最高的就属 GET 请求和 POST 请求了尤其是在中、小型公司基本只会使用这两种请求来实现一个项目。
1.相同点和最本质的区别
1.1 相同点
GET 请求和 POST 请求底层都是基于 TCP/IP 协议实现的使用二者中的任意一个都可以实现客户端和服务器端的双向交互。
1.2 最本质的区别
GET 和 POST 最本质的区别是“约定和规范”上的区别在规范中定义 GET 请求是用来获取资源的也就是进行查询操作的而 POST 请求是用来传输实体对象的因此会使用 POST 来进行添加、修改和删除等操作。 当然如果严格按照规范来说删除操作应该使用 DELETE 请求才对但在实际开发中使用 POST 来进行删除的用法更常见一些。 按照约定来说GET 和 POST 的参数传递也是不同的GET 请求是将参数拼加到 URL 上进行参数传递的而 POST 是将请参数写入到请求正文中传递的如下图所示
2.非本质区别
2.1 缓存不同
GET 请求一般会被缓存比如常见的 CSS、JS、HTML 请求等都会被缓存而 POST 请求默认是不进行缓存的。
2.2 参数长度限制不同
GET 请求的参数是通过 URL 传递的而 URL 的长度是有限制的通常为 2k当然浏览器厂商不同、版本不同这个限制的大小值可能也不同但相同的是它们都会对 URL 的大小进行限制而 POST 请求参数是存放在请求正文request body中的所以没有大小限制。
2.3 回退和刷新不同
GET 请求可以直接进行回退和刷新不会对用户和程序产生任何影响而 POST 请求如果直接回滚和刷新将会把数据再次提交如下图所示
2.4 历史记录不同
GET 请求的参数会保存在历史记录中而 POST 请求的参数不会保留到历史记录中。
2.5 书签不同
GET 请求的地址可被收藏为书签而 POST 请求的地址不能被收藏为书签。
3.总结
GET 和 POST 是 HTTP 请求中最常用的两种请求方法它们的底层都是基于 TCP/IP 实现的。它们的区别主要体现在 5 个方面缓存不同、参数长度限制不同、回退和刷新不同、历史记录不同、能否保存为书签不同但它们最大的区别是规范和约定上的不同规范中定义 GET 是用来获取信息的而 POST 是用来传递实体的并且 GET 请求的参数要放在 URL 上而 POST 请求的参数要放在请求正文中。
09.WebSockt
一、内容概览
WebSocket的出现使得浏览器具备了实时双向通信的能力。本文由浅入深介绍了WebSocket如何建立连接、交换数据的细节以及数据帧的格式。此外还简要介绍了针对WebSocket的安全攻击以及协议是如何抵御类似攻击的。
二、什么是WebSocket
HTML5开始提供的一种浏览器与服务器进行全双工通讯的网络技术属于应用层协议。它基于TCP传输协议并复用HTTP的握手通道。
对大部分web开发者来说上面这段描述有点枯燥其实只要记住几点
WebSocket可以在浏览器里使用支持双向通信使用很简单
1、有哪些优点
说到优点这里的对比参照物是HTTP协议概括地说就是支持双向通信更灵活更高效可扩展性更好。
支持双向通信实时性更强。更好的二进制支持。较少的控制开销。连接创建后ws客户端、服务端进行数据交换时协议控制的数据包头部较小。在不包含头部的情况下服务端到客户端的包头只有2~10字节取决于数据包长度客户端到服务端的的话需要加上额外的4字节的掩码。而HTTP协议每次通信都需要携带完整的头部。支持扩展。ws协议定义了扩展用户可以扩展协议或者实现自定义的子协议。比如支持自定义压缩算法等
对于后面两点没有研究过WebSocket协议规范的同学可能理解起来不够直观但不影响对WebSocket的学习和使用。
2、需要学习哪些东西
对网络应用层协议的学习来说最重要的往往就是连接建立过程、数据交换教程。当然数据的格式是逃不掉的因为它直接决定了协议本身的能力。好的数据格式能让协议更高效、扩展性更好。
下文主要围绕下面几点展开
如何建立连接如何交换数据数据帧格式如何维持连接
三、入门例子
在正式介绍协议细节前先来看一个简单的例子有个直观感受。例子包括了WebSocket服务端、WebSocket客户端网页端。完整代码可以在 这里 找到。
这里服务端用了ws这个库。相比大家熟悉的socket.iows实现更轻量更适合学习的目的。
1、服务端
代码如下监听8080端口。当有新的连接请求到达时打印日志同时向客户端发送消息。当收到到来自客户端的消息时同样打印日志。
var app require(express)();
var server require(http).Server(app);
var WebSocket require(ws);var wss new WebSocket.Server({ port: 8080 });wss.on(connection, function connection(ws) {console.log(server: receive connection.);ws.on(message, function incoming(message) {console.log(server: received: %s, message);});ws.send(world);
});app.get(/, function (req, res) {res.sendfile(__dirname /index.html);
});app.listen(3000);2、客户端
代码如下向8080端口发起WebSocket连接。连接建立后打印日志同时向服务端发送消息。接收到来自服务端的消息后同样打印日志。
scriptvar ws new WebSocket(ws://localhost:8080);ws.onopen function () {console.log(ws onopen);ws.send(from client: hello);};ws.onmessage function (e) {console.log(ws onmessage);console.log(from server: e.data);};
/script3、运行结果
可分别查看服务端、客户端的日志这里不展开。
服务端输出
server: receive connection.
server: received hello客户端输出
client: ws connection is open
client: received world四、如何建立连接
前面提到WebSocket复用了HTTP的握手通道。具体指的是客户端通过HTTP请求与WebSocket服务端协商升级协议。协议升级完成后后续的数据交换则遵照WebSocket的协议。
1、客户端申请协议升级
首先客户端发起协议升级请求。可以看到采用的是标准的HTTP报文格式且只支持GET方法。
GET / HTTP/1.1
Host: localhost:8080
Origin: http://127.0.0.1:3000
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: w4v7O6xFTi36lq3RNcgctw重点请求首部意义如下
Connection: Upgrade表示要升级协议Upgrade: websocket表示要升级到websocket协议。Sec-WebSocket-Version: 13表示websocket的版本。如果服务端不支持该版本需要返回一个Sec-WebSocket-Versionheader里面包含服务端支持的版本号。Sec-WebSocket-Key与后面服务端响应首部的Sec-WebSocket-Accept是配套的提供基本的防护比如恶意的连接或者无意的连接。 注意上面请求省略了部分非重点请求首部。由于是标准的HTTP请求类似Host、Origin、Cookie等请求首部会照常发送。在握手阶段可以通过相关请求首部进行 安全限制、权限校验等。 2、服务端响应协议升级
服务端返回内容如下状态代码101表示协议切换。到此完成协议升级后续的数据交互都按照新的协议来。
HTTP/1.1 101 Switching Protocols
Connection:Upgrade
Upgrade: websocket
Sec-WebSocket-Accept: Oy4NRAQ13jhfONC7bP8dTKb4PTU备注每个header都以\r\n结尾并且最后一行加上一个额外的空行\r\n。此外服务端回应的HTTP状态码只能在握手阶段使用。过了握手阶段后就只能采用特定的错误码。 3、Sec-WebSocket-Accept的计算
Sec-WebSocket-Accept根据客户端请求首部的Sec-WebSocket-Key计算出来。
计算公式为
将Sec-WebSocket-Key跟258EAFA5-E914-47DA-95CA-C5AB0DC85B11拼接。通过SHA1计算出摘要并转成base64字符串。
伪代码如下
toBase64( sha1( Sec-WebSocket-Key 258EAFA5-E914-47DA-95CA-C5AB0DC85B11 ) )验证下前面的返回结果
const crypto require(crypto);
const magic 258EAFA5-E914-47DA-95CA-C5AB0DC85B11;
const secWebSocketKey w4v7O6xFTi36lq3RNcgctw;let secWebSocketAccept crypto.createHash(sha1).update(secWebSocketKey magic).digest(base64);console.log(secWebSocketAccept);
// Oy4NRAQ13jhfONC7bP8dTKb4PTU五、数据帧格式
客户端、服务端数据的交换离不开数据帧格式的定义。因此在实际讲解数据交换之前我们先来看下WebSocket的数据帧格式。
WebSocket客户端、服务端通信的最小单位是帧frame由1个或多个帧组成一条完整的消息message。
发送端将消息切割成多个帧并发送给服务端接收端接收消息帧并将关联的帧重新组装成完整的消息
本节的重点就是讲解数据帧的格式。详细定义可参考 RFC6455 5.2节 。
1、数据帧格式概览
下面给出了WebSocket数据帧的统一格式。熟悉TCP/IP协议的同学对这样的图应该不陌生。
从左到右单位是比特。比如FIN、RSV1各占据1比特opcode占据4比特。内容包括了标识、操作代码、掩码、数据、数据长度等。下一小节会展开 0 1 2 30 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1--------------------------------------------------------|F|R|R|R| opcode|M| Payload len | Extended payload length ||I|S|S|S| (4) |A| (7) | (16/64) ||N|V|V|V| |S| | (if payload len126/127) || |1|2|3| |K| | |------------------------- - - - - - - - - - - - - - - - | Extended payload length continued, if payload len 127 | - - - - - - - - - - - - - - - -------------------------------| |Masking-key, if MASK set to 1 |--------------------------------------------------------------| Masking-key (continued) | Payload Data |-------------------------------- - - - - - - - - - - - - - - - : Payload Data continued ... : - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | Payload Data continued ... |---------------------------------------------------------------2、数据帧格式详解
针对前面的格式概览图这里逐个字段进行讲解如有不清楚之处可参考协议规范或留言交流。
FIN1个比特。
如果是1表示这是消息message的最后一个分片fragment如果是0表示不是是消息message的最后一个分片fragment。
RSV1, RSV2, RSV3各占1个比特。
一般情况下全为0。当客户端、服务端协商采用WebSocket扩展时这三个标志位可以非0且值的含义由扩展进行定义。如果出现非零的值且并没有采用WebSocket扩展连接出错。
Opcode: 4个比特。
操作代码Opcode的值决定了应该如何解析后续的数据载荷data payload。如果操作代码是不认识的那么接收端应该断开连接fail the connection。可选的操作代码如下
%x0表示一个延续帧。当Opcode为0时表示本次数据传输采用了数据分片当前收到的数据帧为其中一个数据分片。%x1表示这是一个文本帧frame%x2表示这是一个二进制帧frame%x3-7保留的操作代码用于后续定义的非控制帧。%x8表示连接断开。%x9表示这是一个ping操作。%xA表示这是一个pong操作。%xB-F保留的操作代码用于后续定义的控制帧。
Mask: 1个比特。
表示是否要对数据载荷进行掩码操作。从客户端向服务端发送数据时需要对数据进行掩码操作从服务端向客户端发送数据时不需要对数据进行掩码操作。
如果服务端接收到的数据没有进行过掩码操作服务端需要断开连接。
如果Mask是1那么在Masking-key中会定义一个掩码键masking key并用这个掩码键来对数据载荷进行反掩码。所有客户端发送到服务端的数据帧Mask都是1。
掩码的算法、用途在下一小节讲解。
Payload length数据载荷的长度单位是字节。为7位或716位或164位。
假设数Payload length x如果
x为0~126数据的长度为x字节。x为126后续2个字节代表一个16位的无符号整数该无符号整数的值为数据的长度。x为127后续8个字节代表一个64位的无符号整数最高位为0该无符号整数的值为数据的长度。
此外如果payload length占用了多个字节的话payload length的二进制表达采用网络序big endian重要的位在前。
Masking-key0或4字节32位
所有从客户端传送到服务端的数据帧数据载荷都进行了掩码操作Mask为1且携带了4字节的Masking-key。如果Mask为0则没有Masking-key。
备注载荷数据的长度不包括mask key的长度。
Payload data(xy) 字节
载荷数据包括了扩展数据、应用数据。其中扩展数据x字节应用数据y字节。
扩展数据如果没有协商使用扩展的话扩展数据数据为0字节。所有的扩展都必须声明扩展数据的长度或者可以如何计算出扩展数据的长度。此外扩展如何使用必须在握手阶段就协商好。如果扩展数据存在那么载荷数据长度必须将扩展数据的长度包含在内。
应用数据任意的应用数据在扩展数据之后如果存在扩展数据占据了数据帧剩余的位置。载荷数据长度 减去 扩展数据长度就得到应用数据的长度。
3、掩码算法
掩码键Masking-key是由客户端挑选出来的32位的随机数。掩码操作不会影响数据载荷的长度。掩码、反掩码操作都采用如下算法
首先假设
original-octet-i为原始数据的第i字节。transformed-octet-i为转换后的数据的第i字节。j为i mod 4的结果。masking-key-octet-j为mask key第j字节。
算法描述为 original-octet-i 与 masking-key-octet-j 异或后得到 transformed-octet-i。 j i MOD 4 transformed-octet-i original-octet-i XOR masking-key-octet-j 六、数据传递
一旦WebSocket客户端、服务端建立连接后后续的操作都是基于数据帧的传递。
WebSocket根据opcode来区分操作的类型。比如0x8表示断开连接0x0-0x2表示数据交互。
1、数据分片
WebSocket的每条消息可能被切分成多个数据帧。当WebSocket的接收方收到一个数据帧时会根据FIN的值来判断是否已经收到消息的最后一个数据帧。
FIN1表示当前数据帧为消息的最后一个数据帧此时接收方已经收到完整的消息可以对消息进行处理。FIN0则接收方还需要继续监听接收其余的数据帧。
此外opcode在数据交换的场景下表示的是数据的类型。0x01表示文本0x02表示二进制。而0x00比较特殊表示延续帧continuation frame顾名思义就是完整消息对应的数据帧还没接收完。
2、数据分片例子
直接看例子更形象些。下面例子来自MDN可以很好地演示数据的分片。客户端向服务端两次发送消息服务端收到消息后回应客户端这里主要看客户端往服务端发送的消息。
第一条消息
FIN1, 表示是当前消息的最后一个数据帧。服务端收到当前数据帧后可以处理消息。opcode0x1表示客户端发送的是文本类型。
第二条消息
FIN0opcode0x1表示发送的是文本类型且消息还没发送完成还有后续的数据帧。FIN0opcode0x0表示消息还没发送完成还有后续的数据帧当前的数据帧需要接在上一条数据帧之后。FIN1opcode0x0表示消息已经发送完成没有后续的数据帧当前的数据帧需要接在上一条数据帧之后。服务端可以将关联的数据帧组装成完整的消息。
Client: FIN1, opcode0x1, msghello
Server: (process complete message immediately) Hi.
Client: FIN0, opcode0x1, msgand a
Server: (listening, new message containing text started)
Client: FIN0, opcode0x0, msghappy new
Server: (listening, payload concatenated to previous message)
Client: FIN1, opcode0x0, msgyear!
Server: (process complete message) Happy new year to you too!七、连接保持心跳
WebSocket为了保持客户端、服务端的实时双向通信需要确保客户端、服务端之间的TCP通道保持连接没有断开。然而对于长时间没有数据往来的连接如果依旧长时间保持着可能会浪费包括的连接资源。
但不排除有些场景客户端、服务端虽然长时间没有数据往来但仍需要保持连接。这个时候可以采用心跳来实现。
发送方-接收方ping接收方-发送方pong
ping、pong的操作对应的是WebSocket的两个控制帧opcode分别是0x9、0xA。
举例WebSocket服务端向客户端发送ping只需要如下代码采用ws模块
ws.ping(, false, true);八、Sec-WebSocket-Key/Accept的作用
前面提到了Sec-WebSocket-Key/Sec-WebSocket-Accept在主要作用在于提供基础的防护减少恶意连接、意外连接。
作用大致归纳如下
避免服务端收到非法的websocket连接比如http客户端不小心请求连接websocket服务此时服务端可以直接拒绝连接确保服务端理解websocket连接。因为ws握手阶段采用的是http协议因此可能ws连接是被一个http服务器处理并返回的此时客户端可以通过Sec-WebSocket-Key来确保服务端认识ws协议。并非百分百保险比如总是存在那么些无聊的http服务器光处理Sec-WebSocket-Key但并没有实现ws协议。。。用浏览器里发起ajax请求设置header时Sec-WebSocket-Key以及其他相关的header是被禁止的。这样可以避免客户端发送ajax请求时意外请求协议升级websocket upgrade可以防止反向代理不理解ws协议返回错误的数据。比如反向代理前后收到两次ws连接的升级请求反向代理把第一次请求的返回给cache住然后第二次请求到来时直接把cache住的请求给返回无意义的返回。Sec-WebSocket-Key主要目的并不是确保数据的安全性因为Sec-WebSocket-Key、Sec-WebSocket-Accept的转换计算公式是公开的而且非常简单最主要的作用是预防一些常见的意外情况非故意的。 强调Sec-WebSocket-Key/Sec-WebSocket-Accept 的换算只能带来基本的保障但连接是否安全、数据是否安全、客户端/服务端是否合法的 ws客户端、ws服务端其实并没有实际性的保证。 九、数据掩码的作用
WebSocket协议中数据掩码的作用是增强协议的安全性。但数据掩码并不是为了保护数据本身因为算法本身是公开的运算也不复杂。除了加密通道本身似乎没有太多有效的保护通信安全的办法。
那么为什么还要引入掩码计算呢除了增加计算机器的运算量外似乎并没有太多的收益这也是不少同学疑惑的点。
答案还是两个字安全。但并不是为了防止数据泄密而是为了防止早期版本的协议中存在的代理缓存污染攻击proxy cache poisoning attacks等问题。
1、代理缓存污染攻击
下面摘自2010年关于安全的一段讲话。其中提到了代理服务器在协议实现上的缺陷可能导致的安全问题。猛击出处。 “We show, empirically, that the current version of the WebSocket consent mechanism is vulnerable to proxy cache poisoning attacks. Even though the WebSocket handshake is based on HTTP, which should be understood by most network intermediaries, the handshake uses the esoteric “Upgrade” mechanism of HTTP [5]. In our experiment, we find that many proxies do not implement the Upgrade mechanism properly, which causes the handshake to succeed even though subsequent traffic over the socket will be misinterpreted by the proxy.” [TALKING] Huang, L-S., Chen, E., Barth, A., Rescorla, E., and C. Jackson, “Talking to Yourself for Fun and Profit”, 2010, 在正式描述攻击步骤之前我们假设有如下参与者
攻击者、攻击者自己控制的服务器简称“邪恶服务器”、攻击者伪造的资源简称“邪恶资源”受害者、受害者想要访问的资源简称“正义资源”受害者实际想要访问的服务器简称“正义服务器”中间代理服务器
攻击步骤一
攻击者浏览器 向 邪恶服务器 发起WebSocket连接。根据前文首先是一个协议升级请求。协议升级请求 实际到达 代理服务器。代理服务器 将协议升级请求转发到 邪恶服务器。邪恶服务器 同意连接代理服务器 将响应转发给 攻击者。
由于 upgrade 的实现上有缺陷代理服务器 以为之前转发的是普通的HTTP消息。因此当协议服务器 同意连接代理服务器 以为本次会话已经结束。
攻击步骤二
攻击者 在之前建立的连接上通过WebSocket的接口向 邪恶服务器 发送数据且数据是精心构造的HTTP格式的文本。其中包含了 正义资源 的地址以及一个伪造的host指向正义服务器。见后面报文请求到达 代理服务器 。虽然复用了之前的TCP连接但 代理服务器 以为是新的HTTP请求。代理服务器 向 邪恶服务器 请求 邪恶资源。邪恶服务器 返回 邪恶资源。代理服务器 缓存住 邪恶资源url是对的但host是 正义服务器 的地址。
到这里受害者可以登场了
受害者 通过 代理服务器 访问 正义服务器 的 正义资源。代理服务器 检查该资源的url、host发现本地有一份缓存伪造的。代理服务器 将 邪恶资源 返回给 受害者。受害者 卒。
附前面提到的精心构造的“HTTP请求报文”。
Client → Server:
POST /path/of/attackers/choice HTTP/1.1 Host: host-of-attackers-choice.com Sec-WebSocket-Key: connection-key
Server → Client:
HTTP/1.1 200 OK
Sec-WebSocket-Accept: connection-key2、当前解决方案
最初的提案是对数据进行加密处理。基于安全、效率的考虑最终采用了折中的方案对数据载荷进行掩码处理。
需要注意的是这里只是限制了浏览器对数据载荷进行掩码处理但是坏人完全可以实现自己的WebSocket客户端、服务端不按规则来攻击可以照常进行。
但是对浏览器加上这个限制后可以大大增加攻击的难度以及攻击的影响范围。如果没有这个限制只需要在网上放个钓鱼网站骗人去访问一下子就可以在短时间内展开大范围的攻击。
10.tcp/ip五层模型
应用层Application Layer该层为用户提供应用程序如电子邮件、文件传输、远程登录等。常见的协议有 HTTP、FTP、SMTP 等。传输层Transport Layer该层负责数据传输并保证数据传输的可靠性。常见的协议有 TCP 和 UDP。网络层Internet Layer该层主要解决数据在网络中的路由问题。常见的协议有 IP、ICMP、ARP 等。数据链路层Data Link Layer该层主要解决相邻节点之间的通信问题将比特流转换成帧进行传输。常见的协议有 Ethernet、WiFi 等。物理层Physical Layer该层实现物理连接和比特流传输如网线、光纤等。
11.dns服务器用的是什么协议
DNS同时占用UDP和TCP端口53是公认的这种单个应用协议同时使用两种传输协议的情况在TCP/IP栈也算是个另类。但很少有人知道DNS分别在什么情况下使用这两种协议。
先简单介绍下TCP与UDP。 TCP是一种面向连接的协议提供可靠的数据传输一般服务质量要求比较高的情况使用这个协议。UDP—用户数据报协议是一种无连接的传输层协议提供面向事务的简单不可靠信息传送服务。
TCP与UDP的区别 UDP和TCP协议的主要区别是两者在如何实现信息的可靠传递方面不同。TCP协议中包含了专门的传递保证机制当数据接收方收到发送方传来的信息时会自动向发送方发出确认消息发送方只有在接收到该确认消息之后才继续传送其它信息否则将一直等待直到收到确认信息为止。 与TCP不同UDP协议并不提供数据传送的保证机制。如果在从发送方到接收方的传递过程中出现数据报的丢失协议本身并不能做出任何检测或提示。因此通常人们把UDP协议称为不可靠的传输协议。相对于TCP协议UDP协议的另外一个不同之处在于如何接收突发性的多个数据报。不同于TCPUDP并不能确保数据的发送和接收顺序。事实上UDP协议的这种乱序性基本上很少出现通常只会在网络非常拥挤的情况下才有可能发生。 既然UDP是一种不可靠的网络协议那么还有什么使用价值或必要呢其实不然在有些情况下UDP协议可能会变得非常有用。因为UDP具有TCP所望尘莫及的速度优势。虽然TCP协议中植入了各种安全保障功能但是在实际执行的过程中会占用大量的系统开销无疑使速度受到严重的影响。反观UDP由于排除了信息可靠传递机制将安全和排序等功能移交给上层应用来完成极大降低了执行时间使速度得到了保证。
DNS在进行区域传输的时候使用TCP协议其它时候则使用UDP协议 DNS的规范规定了2种类型的DNS服务器一个叫主DNS服务器一个叫辅助DNS服务器。在一个区中主DNS服务器从自己本机的数据文件中读取该区的DNS数据信息而辅助DNS服务器则从区的主DNS服务器中读取该区的DNS数据信息。当一个辅助DNS服务器启动时它需要与主DNS服务器通信并加载数据信息这就叫做区传送zone transfer。
为什么既使用TCP又使用UDP 首先了解一下TCP与UDP传送字节的长度限制 UDP报文的最大长度为512字节而TCP则允许报文长度超过512字节。当DNS查询超过512字节时协议的TC标志出现删除标志这时则使用TCP发送。通常传统的UDP报文一般不会大于512字节。
区域传送时使用TCP主要有一下两点考虑 1.辅域名服务器会定时一般时3小时向主域名服务器进行查询以便了解数据是否有变动。如有变动则会执行一次区域传送进行数据同步。区域传送将使用TCP而不是UDP因为数据同步传送的数据量比一个请求和应答的数据量要多得多。 2.TCP是一种可靠的连接保证了数据的准确性。
域名解析时使用UDP协议 客户端向DNS服务器查询域名一般返回的内容都不超过512字节用UDP传输即可。不用经过TCP三次握手这样DNS服务器负载更低响应更快。虽然从理论上说客户端也可以指定向DNS服务器查询的时候使用TCP但事实上很多DNS服务器进行配置的时候仅支持UDP查询包。
12.ping命令 用的是什么协议。在哪一层。
ping命令使用的是ICMP协议Internet Control Message Protocol互联网控制报文协议。ICMP是一种网络层协议位于OSI模型的第三层网络层用于在IP网络中传递错误消息和操作指令。ping命令通过发送ICMP Echo Request回显请求消息来测试目标主机是否可达并测量往返延迟时间。当目标主机收到Echo Request消息后会返回一个ICMP Echo Reply回显应答消息给源主机由此可以确认目标主机的可达性以及测量通信延迟。因此ping命令既可以用于诊断网络故障也可以用于测试网络连接速度。
13.能详细讲一下有限状态机怎么解析http报文吗
一、HTTP报文
HTTP的报文格式
起始行 头部字段 空 行 消息正文 其中起始行和头部字段成为Header消息正文称为body。Header和body之间一定要有空行隔开。 请求行的格式 如下 GET /index.html HTTP/1.1 请求方法为GET, url为/index.html版本为HTTP/1.1
而请求头部就是用 key:value 更详细的方式说明HTTP报文。 而我们要做的就是解析这样的http请求并发送应答报文给客户端。
二、程序结构
主程序 recv() 是从套接字中读取http报文数据到buffer中
解析HTTP请求的主函数
parse_content()在parse_content中首先通过parse_line()读取一行 主状态有解析请求行和解析头部两种状态初始状态为解析请求行当解析请求行完毕状态转移到解析头部字段
//部分代码非完整代码
HTTP_CODE parse_content(char* buffer, int checked_index, CHECK_STATE checkstate, int read_index, int start_line)
{
//每次读取一行解析while ((linestatus parse_line(buffer, checked_index, read_index)) LINE_OK){switch (checkstate){case CHECK_STATE_REQUESTLINE://解析请求行{//调用解析请求行函数解析完成后在函数中完成状态转移retcode parse_requestline(szTemp, checkstate);break;}case CHECK_STATE_HEADER://解析头部字段{retcode parse_headers(szTemp);//解析结果被省略了break;}}}if (linestatus LINE_OPEN)//不能读取到完整行{return NO_REQUEST;}else{return BAD_REQUEST;}
}三、完整代码
#include sys/socket.h
#include netinet/in.h
#include arpa/inet.h
#include assert.h
#include stdio.h
#include stdlib.h
#include unistd.h
#include errno.h
#include string.h
#include fcntl.h
#include iostream
using namespace std;
constexpr auto BUFFER_SIZE 4096;
//主状态机状态
//CHECK_STATE_REQUESTLINE 解析请求行CHECK_STATE_HEADER 解析头部字段
enum CHECK_STATE { CHECK_STATE_REQUESTLINE 0, CHECK_STATE_HEADER, CHECK_STATE_CONTENT };
//从状态机状态LINE_OK 完整的一行LINE_OPEN该行尚未读完LINE_BAD 该行有错误
enum LINE_STATUS { LINE_OK 0, LINE_BAD, LINE_OPEN };
//处理http请求的结果 NO_REQUEST 表示读取的请求结果不完整GET_REQUEST 读取了完整正确的http请求BAD_REQUEST表示客户请求有错
enum HTTP_CODE { NO_REQUEST, GET_REQUEST, BAD_REQUEST, FORBIDDEN_REQUEST, INTERNAL_ERROR, CLOSED_CONNECTION };
static const char* szret[] { I get a correct result\n, Something wrong\n };
//次状态机每次读取一行通过读取到/r/n来判断是不是完整的一行
LINE_STATUS parse_line(char* buffer, int checked_index, int read_index)
{char temp;for (; checked_index read_index; checked_index){temp buffer[checked_index];if (temp \r){if ((checked_index 1) read_index){return LINE_OPEN;}else if (buffer[checked_index 1] \n){buffer[checked_index] \0;buffer[checked_index] \0;return LINE_OK;}return LINE_BAD;}else if (temp \n){if ((checked_index 1) buffer[checked_index - 1] \r){buffer[checked_index - 1] \0;buffer[checked_index] \0;return LINE_OK;}return LINE_BAD;}}return LINE_OPEN;
}
//解析请求行 GET url HTTP/1.1
HTTP_CODE parse_requestline(char* szTemp, CHECK_STATE checkstate)
{char* szURL strpbrk(szTemp, \t);if (!szURL){return BAD_REQUEST;}*szURL \0;char* szMethod szTemp;if (strcasecmp(szMethod, GET) 0){printf(The request method is GET\n);}else{return BAD_REQUEST;}szURL strspn(szURL, \t);char* szVersion strpbrk(szURL, \t);if (!szVersion){return BAD_REQUEST;}*szVersion \0;szVersion strspn(szVersion, \t);if (strcasecmp(szVersion, HTTP/1.1) ! 0){return BAD_REQUEST;}if (strncasecmp(szURL, http://, 7) 0){szURL 7;szURL strchr(szURL, /);}if (!szURL || szURL[0] ! /){return BAD_REQUEST;}//URLDecode( szURL );printf(The request URL is: %s\n, szURL);checkstate CHECK_STATE_HEADER;return NO_REQUEST;}
//解析头部字段读取到空行说明头部正确
HTTP_CODE parse_headers(char* szTemp)
{if (szTemp[0] \0){return GET_REQUEST;}else if (strncasecmp(szTemp, Host:, 5) 0){szTemp 5;szTemp strspn(szTemp, \t);printf(the request host is: %s\n, szTemp);}else{printf(I can not handle this header\n);}return NO_REQUEST;}
//解析报文主函数
HTTP_CODE parse_content(char* buffer, int checked_index, CHECK_STATE checkstate, int read_index, int start_line)
{LINE_STATUS linestatus LINE_OK;HTTP_CODE retcode NO_REQUEST;while ((linestatus parse_line(buffer, checked_index, read_index)) LINE_OK){char* szTemp buffer start_line;start_line checked_index;switch (checkstate){case CHECK_STATE_REQUESTLINE:{retcode parse_requestline(szTemp, checkstate);if (retcode BAD_REQUEST){return BAD_REQUEST;}break;}case CHECK_STATE_HEADER:{retcode parse_headers(szTemp);if (retcode BAD_REQUEST){return BAD_REQUEST;}else if (retcode GET_REQUEST){return GET_REQUEST;}break;}default:{return INTERNAL_ERROR;}}}if (linestatus LINE_OPEN){return NO_REQUEST;}else{return BAD_REQUEST;}
}int main(int argc, char* argv[])
{const char *ip 127.0.0.1;int port 8888;
// if (argc 2)
// {
// printf(usage: %s ip_address port_number\n, basename(argv[0]));
// return 1;
// }
// const char* ip argv[1];
// int port atoi(argv[2]);struct sockaddr_in address;bzero(address, sizeof(address));address.sin_family AF_INET;inet_pton(AF_INET, ip, address.sin_addr);address.sin_port htons(port);int listenfd socket(PF_INET, SOCK_STREAM, 0);assert(listenfd 0);int ret bind(listenfd, (struct sockaddr*) address, sizeof(address));assert(ret ! -1);ret listen(listenfd, 5);assert(ret ! -1);struct sockaddr_in client_address;socklen_t client_addrlength sizeof(client_address);int fd accept(listenfd, (struct sockaddr*) client_address, client_addrlength);if (fd 0){printf(errno is: %d\n, errno);}else{char buffer[BUFFER_SIZE];memset(buffer, \0, BUFFER_SIZE);int data_read 0;int read_index 0;int checked_index 0;int start_line 0;CHECK_STATE checkstate CHECK_STATE_REQUESTLINE;while (1){data_read recv(fd, buffer read_index, BUFFER_SIZE - read_index, 0);coutbufferendl;if (data_read -1){printf(reading failed\n);break;}else if (data_read 0){printf(remote client has closed the connection\n);break;}read_index data_read;HTTP_CODE result parse_content(buffer, checked_index, checkstate, read_index, start_line);if (result NO_REQUEST){continue;}else if (result GET_REQUEST){send(fd, szret[0], strlen(szret[0]), 0);break;}else{send(fd, szret[1], strlen(szret[1]), 0);break;}}close(fd);}close(listenfd);return 0;}四、运行
首先服务器上运行解析HTTP请求的代码
客户端发送HTTP请求 1、可以通过命令行 curl 127.0.0.1:8888/url url可以随便写也可以空着
2、可以通过浏览器发起http请求 地址栏输入 127.0.0.1:8888/index.html
服务器运行结果 14.如果解析http请求的时候用户一次性没传完数据如果头部都没传完请求报文长度字段都没传完怎么办
当用户一次性没有传完整个HTTP请求报文时HTTP解析器可能会遇到以下情况
请求头部未传完在等待请求头部的状态下如果读取的数据不足以解析出完整的请求头部则可以等待更多数据到达直到能够解析出完整的请求头部为止。如果连接已经关闭或者超时则可以返回一个错误或异常。请求体未传完Content-Length在等待消息体的状态下如果读取的数据不足以满足Content-Length指定的长度则可以继续等待更多数据到达并将其存储在缓冲区中。当读取到足够数量的字节后就可以开始处理HTTP消息体。如果连接已经关闭或者超时则可以返回一个错误或异常。请求体未传完Transfer-Encoding在等待消息体的状态下如果使用了Transfer-Encoding进行编码则需要根据当前编码类型和剩余数据量来判断是否需要等待更多数据。例如在chunked编码中每个块都有一个长度字段用于指示块大小因此解析器可以依次读取每个块并将其存储在缓冲区中。当所有块都被读取完成后解析器会跳转到processing complete状态并返回结果给调用者。
15.路由表说一下
1.概述
在计算机网络中路由器的主要工作就是为经过路由器的每个数据包寻找一条最佳的传输路径并将该数据有效地传送到目的站点。为了能够实现从众多路径中选择最佳的传输路径路由器中保存了周边网络的拓扑信息和各种路径参数我们将这张表称作路由表。路由表routing table或称路由择域信息库RIB, Routing Information Base是一个存储在路由器或者联网计算机中的电子表格文件或类数据库。路由表存储着指向特定网络地址的路径在有些情况下还记录有路径的路由度量值。路由表建立的主要目标是为了实现路由协议和静态路由选择。
在每一个路由器设备中通常都维护了两张比较相似的表分别为
路由信息表简称为RIB表、路由表转发信息表, 简称为FIB表、转发表
路由表RIB表用来决策路由转发表用来转发分组2.命令
查询RIB表
┌──(root㉿kali)-[~/Desktop]
└─# route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
default 192.168.18.2 0.0.0.0 UG 100 0 0 eth0
192.168.18.0 0.0.0.0 255.255.255.0 U 100 0 0 eth0查询FIB表
┌──(root㉿kali)-[~/Desktop]
└─# route -F
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
default 192.168.18.2 0.0.0.0 UG 100 0 0 eth0
192.168.18.0 0.0.0.0 255.255.255.0 U 100 0 0 eth0由于是主机设备路由表比较简单且不存在多个出接口因此FIB表和RIB是相同的。
3.路由表项内容
目的网络地址(Destination) 子网掩码(Genmask)
网络地址和网络掩码共同确定本机可以达到的目的网络范围
通常情况下目的网络范围包含以下几种情况:
主机地址某个特定主机的网络地址子网地址某个特定子网的网络地址默认路由所有未在路由表中指定的网络地址用0.0.0.0统一匹配用于配置默认网关(kali虚拟机中默认路由显示为default)
网关Gateway 下一跳Next Hop
接口Iface
接口定义了针对特定的网络目的地址路由器用于转发数据包的出接口。即用来确定数据包从哪个网口上发送到下一跳设备
跳数Metric
跳数用于指出路由的成本通常情况下代表:到达目标地址所需要的总路由器个数一个跳数代表经过一个路由器IP数据报首部中的TTL字段就是该数据报所能存活的总跳数。跳数越少往往代表着该路由成本越低跳数越多则说明成本越高。当具有多条达到相同目的网络的路由选项时路由算法会选择具有更少跳数的路由
标志Flags
路由表中常见的flag标记有
U路由是动态的H目标是一个主机G路由指向网关R恢复动态路由产生的表项D由路由的后台程序动态安装M由路由的后台程序修改! 拒绝路由。
引用次数Ref
Linux内核中未使用一般是0
查询次数Use
此路由项被路由软件查找的次数
16.路由表为空怎么找到下一跳
当路由器收到一个待转发的数据报在从路由表得出下一跳路由器的IP地址后不是把这个地址填入IP数据报而是送交数据链路层的网络接口软件。网络接口软件负责把下一跳路由器的IP地址转换成硬件地址必须使用ARP并将此硬件地址放在链路层的MAC帧的首部然后根据这个硬件地址找到下一个路由器。由此可见当发送一连串的数据报时上述的这种查找路由表用ARP得到硬件地址把硬件地址写入MAC帧的首部等过程将不断得进行重复造成一定的开销。
那能否在路由表中不使用IP地址而直接使用硬件地址呢 答案是不可以的因为我们使用抽象的IP地址本来是为了隐藏各种底层网络的复杂性而便于分析和研究问题这样就不可避免要付出代价例如在选择路由时多了一些开销但是反过来如果在路由表中直接使用硬件地址会带来更多的麻烦
17.粘包拆包是什么发生在哪一层
1 什么是粘包
在学习粘包之前先纠正一下读音很多视频教程中将“粘”读作“nián”。经过调研个人更倾向于读“zhān bāo”。
如果在百度百科上搜索“粘包”对应的读音便是“zhān bāo”语义解释为网络技术术语。指TCP协议中发送方发送的若干包数据到接收方接收时粘成一包从接收缓冲区看后一包数据的头紧接着前一包数据的尾。
TCP是面向字节流的协议就是没有界限的一串数据本没有“包”的概念“粘包”和“拆包”一说是为了有助于形象地理解这两种现象。
2 为什么UDP没有粘包
粘包拆包问题在数据链路层、网络层以及传输层都有可能发生。日常的网络应用开发大都在传输层进行由于UDP有消息保护边界不会发生粘包拆包问题因此粘包拆包问题只发生在TCP协议中。
3 粘包拆包发生场景
因为TCP是面向流没有边界而操作系统在发送TCP数据时会通过缓冲区来进行优化例如缓冲区为1024个字节大小。
如果一次请求发送的数据量比较小没达到缓冲区大小TCP则会将多个请求合并为同一个请求进行发送这就形成了粘包问题。
如果一次请求发送的数据量比较大超过了缓冲区大小TCP就会将其拆分为多次发送这就是拆包。
关于粘包和拆包可以参考下图的几种情况 上图中演示了以下几种情况
正常的理想情况两个包恰好满足TCP缓冲区的大小或达到TCP等待时长分别发送两个包*粘包两个包较小间隔时间短发生粘包合并成一个包发送**拆包一个包过大超过缓存区大小拆分成两个或多个包发送**拆包和粘包Packet1过大进行了拆包处理而拆出去的一部分又与Packet2进行粘包处理。*
4 常见的解决方案
对于粘包和拆包问题常见的解决方案有四种
**发送端将每个包都封装成固定的长度**比如100字节大小。如果不足100字节可通过补0或空等进行填充到指定长度发送端在每个包的末尾使用固定的分隔符例如\r\n。如果发生拆包需等待多个包发送过来之后再找到其中的\r\n进行合并例如FTP协议将消息分为头部和消息体头部中保存整个消息的长度只有读取到足够长度的消息之后才算是读到了一个完整的消息*通过自定义协议进行粘包和拆包的处理。*
5 Netty对粘包和拆包问题的处理
Netty对解决粘包和拆包的方案做了抽象提供了一些解码器Decoder来解决粘包和拆包的问题。如
LineBasedFrameDecoder以行为单位进行数据包的解码DelimiterBasedFrameDecoder以特殊的符号作为分隔来进行数据包的解码FixedLengthFrameDecoder以固定长度进行数据包的解码LenghtFieldBasedFrameDecode适用于消息头包含消息长度的协议最常用
基于Netty进行网络读写的程序可以直接使用这些Decoder来完成数据包的解码。对于高并发、大流量的系统来说每个数据包都不应该传输多余的数据所以补齐的方式不可取LenghtFieldBasedFrameDecode更适合这样的场景。
6 小结
TCP协议粘包拆包问题是因为TCP协议数据传输是基于字节流的它不包含消息、数据包等概念需要应用层协议自己设计消息的边界即消息帧Message Framing。如果应用层协议没有使用基于长度或者基于终结符息边界等方式进行处理则会导致多个消息的粘包和拆包。
虽然很多框架中都有现成的解决方案比如Netty但底层的原理我们还是要清楚的而且还要知道有这么会事才能更好的结合场景进行使用。
18.TCP在什么情况下会出现大量time_wait哪个阶段出现
我们首先要弄清楚TIME_WAIT状态是什么TIME_WAIT状态是主动关闭TCP连接的一方即先发起FIN包的一方在发送完最后一个ACK包后进入的状态。系统需要在TIME_WAIT状态下等待2MSLmaximum segment lifetime 后才能释放连接端口。根据RFC 793 MSL是2分钟一般的TCP实现有30秒、1分钟和2分钟不等。进入TIME_WAIT状态等待2MSL主要有两个目的一方面是主动关闭连接的一方在对方没有收到最后一个ACK包时这时对方还会重发FIN收到两个FIN的时间间隔一定小于2MSL有时间可以重发ACK包另一方面处于TIME_WAIT的连接IP和端口组合不能重用这样可以保证被重新分配的socket不会受到之前残留的延迟重发报文影响。
由于主动关闭TCP连接的一方才会进入TIME_WAIT状态一般情况服务器端不会出现TIME_WAIT状态因为大多数情况都是客户端主动发起连接并主动关闭连接。但是某些服务如pop/smtp、ftp却是服务端收到客户端的QUIT命令后主动关闭连接这就造成这类服务器上容易出现大量的TIME_WAIT状态的连接而且并发量越大处于此种状态的连接越多。另外对于被动关闭连接的服务在主动关闭客户端非法请求或清理长时间不活动的连接时这种情况很可能是客户端程序忘记关闭连接也会出现TIME_WAIT的状态。
19.TCP 包头字段… 标志位- 建立连接过程终止连接过程- TIME_WAIT, CLOSE_WAIT 分析属于哪一方
TCP包头中的标志位有URG紧急数据、ACK确认、PSH推送、RST重置连接、SYN同步序号和FIN结束。
建立连接过程中客户端首先向服务器发送一个SYN标志位的TCP包表示请求建立连接。服务器在收到该包后会回复一个SYNACK的TCP包表示已收到请求并同意建立连接。最后客户端再回复一个ACK标志位的TCP包进行确认。
终止连接过程中一方需要向另一方发送一个FIN标志位的TCP包来表示要关闭连接。接收到FIN标志位的一方会回复一个ACK标志位的TCP包进行确认并进入CLOSE_WAIT状态或TIME_WAIT状态。如果是主动发起关闭连接的一方则会进入TIME_WAIT状态如果是被动响应关闭连接请求的一方则会进入CLOSE_WAIT状态。
在TIME_WAIT和CLOSE_WAIT状态下均属于被动响应关闭请求的一方。在这两个状态下通信双方都不能发送新数据但是仍然能够接收对方发送来的数据。在经过一定时间后处于TIME_WAIT状态的一方才能彻底释放资源并完成与对方断开连接而处于CLOSE_WAIT状态的一方则需要等待对方最终关闭连接才能彻底释放资源。
20.TCP 建立连接过程 - SYN ACK 包能不能拆开来发
TCP建立连接过程中客户端向服务器发送SYN标志位的TCP包而服务器在收到该包后需要回复一个SYNACK标志位的TCP包。这个SYNACK包不能拆开来发因为它是一个整体其中既包含了SYN标志位表示同意建立连接又包含了ACK标志位表示确认客户端的请求。
如果将SYN和ACK分别单独发送则无法保证通信的可靠性。因为只有当服务器同时收到了客户端发送的SYN和确认收到该SYN的ACK才能确认建立连接成功并开始进行数据传输。如果SYN和ACK不是同时被接收到则无法建立正确的连接。
因此在TCP建立连接过程中必须按照规定格式发送完整的SYNACK包才能够成功建立连接。
21.讲讲quic/听说过哪些快速重传算法/timewait状态干啥用的
TCP中的快速重传算法主要有以下几种
SACKSelective Acknowledgment算法允许接收方向发送方反馈丢失数据包的序列号从而避免不必要的重传。FACKForward Acknowledgment算法在接收方缓存区有空间时可以提前向发送方发送确认信息告诉它哪些数据已经成功接收。D-SACKDuplicate Selective Acknowledgment算法当发生数据包乱序或丢失时不仅通知发送方这个事实还向其指出该问题所在的数据段和丢失/乱序的字节位置。TCP NewReno相比于早期TCP Reno在检测到快速重传事件后采取了更好的措施来恢复拥塞窗口大小并在一定程度上优化了网络吞吐量。
22.提到了TCP黏包怎么解决固定包头接收指定内存长度
黏包问题是指在传输过程中多个数据包被合并成了一个或者一个数据包被拆分成了多个造成接收方无法正确解析。解决黏包问题的方法主要有以下两种
固定包头接收发送方在每个数据包前加上固定长度的头部信息接收方先读取头部信息获取数据包长度再根据长度截取对应的数据。这样可以保证每次接收到的数据都是完整的。指定内存长度发送方在每个数据包前不添加任何头部信息而是在尾部添加一个特殊字符例如换行符“\n”接收方按照特殊字符进行切割并且预先给缓存区分配足够长的空间来容纳整个消息。这样也能确保接收到的数据都是完整的。
23.查看网络状况以为是netstate其实是ping、traceroute紧张忘记说了
使用ping命令在命令行中输入“ping 目标IP地址或域名”回车后会显示与目标主机之间的网络延迟和数据包传输情况。如果出现丢包现象则说明网络存在问题。使用tracert命令在命令行中输入“tracert 目标IP地址或域名”回车后会显示到达目标主机所经过的路由节点以及每个节点的延迟时间。通过分析延迟时间可以确定网络问题出现的位置。使用网络性能监视器操作系统自带了一些网络性能监视工具如Windows下的资源监视器、Linux下的iftop等可以实时监测网络流量、带宽利用率、连接数等指标有助于发现和解决网络问题。使用第三方网络工具还有许多第三方的网络检测工具如Wireshark、NetScanTools等这些工具提供更详细和全面的信息来帮助用户诊断和调试网络故障。
24.抓包工具wireshark紧张又给忘了靠
一、Wireshark抓包介绍
1、WireShark简介
Wireshark是一个网络封包分析软件。网络封包分析软件的功能是撷取网络封包并尽可能显示出最为详细的网络封包资料。Wireshark使用WinPCAP作为接口直接与网卡进行数据报文交换。
2、 WireShark的应用
网络管理员使用Wireshark 来检测网络问题 网络安全工程师使用Wireshark来检查资讯安全相关问题 开发者使用Wireshark 来为新的通讯协议除错 普通使用者使用Wireshark来学习网络协议的相关知识。 当然有的人也会“居心叵测”的用它来寻找一些敏感信息…
3、 WireShark抓数据包技巧
(1)确定Wireshark的物理位置。如果没有一个正确的位置启动Wireshark后会花费很长的时间捕获一些与自己无关的数据。(2)选择捕获接口。一般都是选择连接到Internet网络的接口这样才可以捕获到与网络相关的数据。否则捕获到的其它数据对自己也没有任何帮助。(3)使用捕获过滤器。通过设置捕获过滤器可以避免产生过大的捕获数据。这样用户在分析数据时也不会受其它数据干扰。而且还可以为用户节约大量的时间。e(4)使用显示过滤器。通常使用捕获过滤器过滤后的数据往往还是很复杂。为了使过滤的数据包再更细致此时使用显示过滤器进行过滤。火(5)使用着色规则。通常使用显示过滤器过滤后的数据都是有用的数据包。如果想更加突出的显示某个会话可以使用着色规则高亮显示。(6)构建图表。如果用户想要更明显的看出一个网络中数据的变化情况使用图表的形式可以很方便的展现数据分布情况。(7)重组数据。当传输较大的图片或文件时需要将信息分布在多个数据包中。这时候就需要使用重组数据的方法来抓取完整的数据。Wireshark的重组功能可以重组一个会话中不同数据包的信息或者是重组一个完整的图片或文件。
二、Wireshark抓包入门操作
1、常见协议包
本节课主要分析以下几种协议类型。
ARP协议ICMP协议TCP协议UDP协议DNS协议HTTP协议
2、查看本机要抓包的网络 输入指令ipconfig找到对应的网络 3、混杂模式介绍
混杂模式概述:混杂模式就是接收所有经过网卡的数据包包括不是发给本机的包即不验证MAC地址。普通模式下网卡只接收发给本机的包包括广播包传递给上层程序其它的包一律丢弃。一般来说混杂模式不会影响网卡的正常工作多在网络监听工具上使用。
4、如何开起混杂模式 三、Wireshark过滤器使用
1、开启以上的混淆模式抓取接口上使用混杂模式直接进行抓包 例1对TCP协议的包进行筛选 例2筛选出ACK相关的包 。SYN1、ACK0客户端请求向服务端建立连接。 例3抓取指定条件的包。tcp.flags.fin 1 当 FIN1 时表明数据已经发送完毕要求释放连接 例4筛选出ARP数据包 例5筛选出udp属于传输层的数据包 我们使用过滤器输入“udp”以筛选出udp报文。但是为什么输入udp之后出现那么多种协议呢?原因就是oicq以及dns都是基于udp的传输层之上的协议
扩展:客户端向DNS服务器查询域名一般返回的内容都不超过512字节用UDP传输即可。不用经过三次握手这样DNS服务器负载更低响应更快。理论上说客户端也可以指定向DNS服务器查询时用TCP但事实上很多 DNS服务器进行配置的时候仅支持UDP查询包。
例6http请求 例7dns数据包 例8数据包条件筛选 其实我们不仅可以对协议类型进行筛选我们还有跟多的筛选条件比如源地址目的地址等等例6:筛选源地址是192.168.1.53或目的地址是192.168.1.1 例9本机向外发或接受的所有数据包 四、ARP协议
1、Arp协议解读
协议分析的时候我们关闭混淆模式避免一些干扰的数据包存在常用协议分析-ARP协议(英语:Address Resolution Protocol细与︰AKP) 是一个通过解析网层地址来找寻数据链路层地址的网络传输协议它在IPv4中极其重要。ARP是通过网络地址来定位MAC地址。主机向目标机器发送信息时ARP请求广播到局域网络上的所有主机并接收返回消息以此确定目标的物理地址收到返回消息后将该IP地址和物理地址存入本机ARP缓存中并保留一定时间下次请求时直接查询ARP缓存以节约资源。
2、分析ARP包 五、ICMP抓包与解读
1、先Ping一个地址获得ICMP包 2、再筛选过滤icmp格式包 工作过程:
本机发送一个ICMP Echo Request的包接收方返回一个ICMP Echo Reply包含了接受到数据拷贝和一些其他指令
六、TCP的3次握手协议
1、清空数据包然后筛选tcp开始抓包 选中一个包进行解读 七、TCP连接断开的4次挥手
我们分析一下过程我们在终端输入EXIT实际上是在我们Kali 上执行的命令表示我们SSHD的Server端向客户端发起关闭链接请求。 我们分析一下过程我们在终端输入EXIT实际上是在我们Kali上执行的命令表示我们SSHD的Server端向客户端发起关闭链接请求。第一次挥手:服务端发送一个[FINACK]表示自己没有数据要发送了想断开连接,并进入FIN_WAIT_1状态第二次挥手:客户端收到FIN后知道不会再有数据从服务端传来发送ACK进行确认确认序号为收到序号1(与SYN相同一个FIN占用一个序号)客户端进入CLOSE_WAIT状态.第三次挥手:客户端发送[FINACK]给对方表示自己没有数据要发送了客户端进入LAST_ACK状态然后直接断开TCP会话的连接释放相应的资源。第四次挥手:服务户端收到了客户端的FIN信令后进入TIMED_WAIT 状态并发迂ACK确认消息。服务端在TIMED_WAIT 状态下等待一段时间没有数据到来就认为对面已经收到了自己发送的ACK并正确关闭了进入 CLOSE状态自己也断开了TCP连接释放所有资源。当客户端收到服务端的ACK回应后会进入CLOSE状态并关闭本端的会话接口释放相应资源。
数据流的统计 八、wireshark常用过滤条件
1、常用条件
‘eq’和’’ 等同and 并且or 或者‘!’ 和’not’ 取反
2、针对IP地址过滤
1.源地址ip.src 192.168… 2.目的地址ip.dst 192.168.xx 3.不看源或目的地址ip.addr 192.168.xx
3、针对协议过滤
1.某种协议的数据包 直接输入协议名字 如http 2.排除某种协议 not tcp 或者 tcp
4、针对端口过滤
1.捕获某端口的数据包 tcp.port 80 tcp.srcport 80 tcp.dstport 80 2.捕获多端口 udp.port 2048
5、针对长度和内容过滤
1.长度过滤 data.len 0 udp.lenth 30 http.content_lenth 20 2.数据包内容过滤 http.request.uri matches “vipscu”(匹配http请求中含有vipscu字段的请求信息)
25.TCP 2MSL说一下为什么
TCP 2MSL是指TCP连接关闭后等待两倍的最大报文段生存时间Maximum Segment Lifetime后才能释放该连接所占用的资源。这个时间通常为60秒左右。
TCP 2MSL存在的主要原因是防止网络上旧数据包延迟到达时被误认为是新连接从而引起不必要的问题。当一个TCP连接关闭时可以通过发送FIN、ACK和RST等控制报文告知对端关闭操作已完成。但由于各种因素如网络拥堵、路由器故障或重传机制等可能会导致已经关闭的连接在某些节点上仍然存在数据包滞留并且可能被误认为是新连接。如果没有适当的延迟时间这些旧数据包可能会干扰新建立的连接。
因此在TCP 2MSL期间内维护该连接状态信息以便处理任何晚到达的报文段或复制报文段。在这段时间内如果收到了新的数据包则需要重新开始计算2MSL时间并持续等待更长的时间来确保所有延迟到达的数据都得到处理。