Java问答知识总结篇-网络基础


Java问答知识总结篇-基础知识
Java问答知识总结篇-JVM
Java问答知识总结篇-多线程&并发编程
Java问答知识总结篇-网络基础
Java问答知识总结篇-Spring
Java问答知识总结篇-Spring Boot
Java问答知识总结篇-Mybatis
Java问答知识总结篇-MySQL
Java问答知识总结篇-Redis
Java问答知识总结篇-MQ
Java问答知识总结篇-Nginx
Java问答知识总结篇-分布式
Java问答知识总结篇-Spring Cloud
Java问答知识总结篇-Dubbo
Java问答知识总结篇-Zookeeper
Java问答知识总结篇-ElasticSearch
Java问答知识总结篇-Netty
Java问答知识总结篇-场景分析题

HTTP 响应码有哪些?分别代表什么含义?

  • 200:成功,Web 服务器成功处理了客户端的请求。
  • 301:永久重定向,当客户端请求一个网址的时候,Web 服务器会将当前请求重定向到另一个网址,搜索引擎会抓取重定向后网页的内容并且将旧的网址替换为重定向后的网址。
  • 302:临时重定向,搜索引擎会抓取重定向后网页的内容而保留旧的网址,因为搜索引擎认为重定向后的网址是暂时的。
  • 400:客户端请求错误,多为参数不合法导致 Web 服务器验参失败。
  • 404:未找到,Web 服务器找不到资源。
  • 500:Web 服务器错误,服务器处理客户端请求的时候发生错误。
  • 503:服务不可用,服务器停机。
  • 504:网关超时。

状态码开头代表类型:

状态码301和302的区别是什么?

共同点:301和302状态码都表示重定向,就是说浏览器在拿到服务器返回的这个状态码后会自动跳转到一个新的URL地址,这个地址可以从响应的Location首部中获取(用户看到的效果就是他输入的地址A瞬间变成了另一个地址B)。
不同点:301表示旧地址A的资源已经被永久地移除了(这个资源不可访问了),搜索引擎在抓取新内容的同时也将旧的网址交换为重定向之后的网址;302表示旧地址A的资源还在(仍然可以访问),这个重定向只是临时地从旧地址A跳转到地址B,搜索引擎会抓取新的内容而保存旧的网址。 SEO中302好于301。

补充,重定向原因

  1. 网站调整(如改变网页目录结构);
  2. 网页被移到一个新地址;
  3. 网页扩展名改变(如应用需要把.php改成.Html或.shtml)。

Forward 和 Redirect 的区别

  • 浏览器 URL 地址:Forward 是服务器内部的重定向,服务器内部请求某个 servlet,然后获取响应的内容,浏览器的 URL 地址是不会变化的;Redirect 是客户端请求服务器,然后服务给客户端返回了一个 302 状态码和新的 location,客户端重新发起 HTTP 请求,服务器给客户端响应 location 对应的 URL 地址,浏览器的 URL 地址发生了变化。
  • 数据的共享:Forward 是服务器内部的重定向,request 在整个重定向过程中是不变的,request 中的信息在 servlet 间是共享的。Redirect 发起了两次 HTTP 请求分别使用不同的request。
  • 请求的次数:Forward 只有一次请求;Redirect 有两次请求。

Get 和 Post 请求有哪些区别

用途

  • get 请求用来从服务器获取资源
  • post 请求用来向服务器提交数据

表单的提交方式

  • get 请求直接将表单数据以 name1=value1&name2=value2 的形式拼接到 URL 上http://www.baidu.com/action?name1=value1&name2=value2,多个参数参数值需要用 & 连接起来并且用 ? 拼接到 action 后面;
  • post 请求将表单数据放到请求头或者请求的消息体中。

传输数据的大小限制

  • get 请求传输的数据受到 URL 长度的限制,而 URL 长度是由浏览器决定的;
  • post 请求传输数据的大小理论上来说是没有限制的。

参数的编码

  • get 请求的参数会在地址栏明文显示,使用 URL 编码的文本格式传递参数;
  • post 请求使用二进制数据多重编码传递参数。

缓存

  • get 请求可以被浏览器缓存被收藏为标签;
  • post 请求不会被缓存也不能被收藏为标签。

说说 TCP 与 UDP 的区别,以及各自的优缺点

  • TCP面向连接(如打电话要先拨号建立连接),UDP是无连接的,即发送数据之前不需要建立连接。
  • TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付。TCP通过校验和,重传控制,序号标识,滑动窗口,确认应答实现可靠传输。如丢包时的重发控制,还可以对次序乱掉的分包进行顺序控制。
  • UDP具有较好的实时性,工作效率比TCP高,适用于对高速传输和实时性有较高的通信或广播通信。
  • 每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信。
  • TCP对系统资源要求较多,UDP对系统资源要求较少。

总结如表:

TCP 用于在传输层有必要实现可靠传输的情况,UDP 用于对高速传输和实时性有较高要求的通信。TCP 和 UDP 应该根据应用目的按需使用。

UDP TCP
是否连接 无连接 面向连接
是否可靠 不可靠传输,不使用流量控制和拥塞控制 可靠传输,使用流量控制和拥塞控制
是否有序 无序 有序,消息在传输过程中可能会乱序,TCP 会重新排序
传输速度
连接对象个数 支持一对一,一对多,多对一和多对多交互通信 只能是一对一通信
传输方式 面向报文 面向字节流
首部开销 首部开销小,仅8字节 首部最小20字节,最大60字节
适用场景 适用于实时应用(IP电话、视频会议、直播等) 适用于要求可靠传输的应用,例如文件传输

UDP 和 TCP 对应的应用场景是什么?

TCP 是面向连接,能保证数据的可靠性交付,因此经常用于:

  • FTP文件传输
  • HTTP / HTTPS

UDP 面向无连接,它可以随时发送数据,再加上UDP本身的处理既简单又高效,因此经常用于:

  • 包总量较少的通信,如 DNS 、SNMP等
  • 视频、音频等多媒体通信
  • 广播通信

说一下 HTTP 和 HTTPS 的区别

端口不同:HTTP和 HTTPS 的连接方式不同,使用的端口也不一样,HTTP是80, HTTPS 用的是443。

消耗资源:和HTTP相比,HTTPS通信会因为加解密的处理消耗更多的CPU和内存资源。

开销: HTTPS 通信需要证书,这类证书通常需要向认证机构申请或者付费购买。

说说HTTP、TCP、Socket 的关系是什么

  • TCP/IP 代表传输控制协议/网际协议,指的是一系列协议族。
  • HTTP 本身就是一个协议,是从 Web 服务器传输超文本到本地浏览器的传送协议。
  • Socket 是 TCP/IP 网络的 API ,其实就是一个门面模式,它把复杂的 TCP/IP 协议族隐藏在Socket 接口后面。对用户来说,一组简单的接口就是全部,让 Socket 去组织数据,以符合指定的协议。

综上所述:

  • 需要 IP 协议来连接网络
  • TCP 是一种允许我们安全传输数据的机制,使用 TCP 协议来传输数据的 HTTP 是 Web 服务器和客户端使用的特殊协议。
  • HTTP 基于 TCP 协议,所以可以使用 Socket 去建立一个 TCP 连接。

说一下HTTP的长连接与短连接的区别

HTTP协议的长连接和短连接,实质上是TCP协议的长连接和短连接。

短连接

在HTTP/1.0中默认使用短链接,也就是说,浏览器和服务器每进行一次HTTP操作,就建立一次连接,但任务结束就中断连接。如果客户端访问的某个HTML或其他类型的Web资源,如 JavaScript文件、图像文件、 CSS 文件等。当浏览器每遇到这样一个Web资源,就会建立一个HTTP会话。

长连接

HTTP/1.1起,默认使用长连接,用以保持连接特性。在使用长连接的情况下,当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭。如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接。Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间。

HTTP请求报文和响应报文的格式?

请求报文格式:

  1. 请求行(请求方法+URI协议+版本)
  2. 请求头部
  3. 空行
  4. 请求主体
GET/sample.jspHTTP/1.1 请求行
Accept:image/gif.image/jpeg, 请求头部
Accept-Language:zh-cn
Connection:Keep-Alive
Host:localhost
User-Agent:Mozila/4.0(compatible;MSIE5.01;Window NT5.0)
Accept-Encoding:gzip,deflate

username=jinqiao&password=1234 请求主体

响应报文:

  1. 状态行(版本+状态码+原因短语)
  2. 响应首部
  3. 空行
  4. 响应主体
HTTP/1.1 200 OK
Server:Apache Tomcat/5.0.12
Date:Mon,6Oct2003 13:23:42 GMT
Content-Length:112

<html>
    <head>
        <title>HTTP响应示例<title>
    </head>
    <body>
        Hello HTTP!
    </body>
</html>

HTTP1.0和HTTP1.1的区别?

  • 长连接:HTTP 1.1支持长连接(Persistent Connection)和请求的流水线(Pipelining)处理,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟,在HTTP1.1中默认开启Connection:keep-alive,一定程度上弥补了HTTP1.0每次请求都要创建连接的缺点。

  • 缓存处理:在HTTP1.0中主要使用header里的If-Modified-Since,Expires来做为缓存判断的标准,HTTP1.1则引入了更多的缓存控制策略,可供选择的缓存头来控制缓存策略。

  • 带宽优化及网络连接的使用:HTTP1.0中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,HTTP1.1则在请求头引入了range头域,它允许只请求资源的某个部分,即返回码是206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接。

  • 错误通知的管理:在HTTP1.1中新增了24个错误状态响应码,如409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除。

  • Host头处理:在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址。HTTP1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会报告一个错误(400 Bad Request)。

HTTP1.1和 HTTP2.0的区别?

HTTP2.0相比HTTP1.1支持的特性:

  • 新的二进制格式:HTTP1.1的解析是基于文本。基于文本协议的格式解析存在天然缺陷,文本的表现形式有多样性,要做到健壮性考虑的场景必然很多,二进制则不同,只认0和1的组合。基于这种考虑HTTP2.0的协议解析决定采用二进制格式,实现方便且健壮。

  • 多路复用:即连接共享,即每一个request都是用作连接共享机制的。一个request对应一个id,这样一个连接上可以有多个request,每个连接的request可以随机的混杂在一起,接收方可以根据request的 id将request再归属到各自不同的服务端请求里面。

  • 头部压缩:HTTP1.1的头部(header)带有大量信息,而且每次都要重复发送;HTTP2.0使用encoder来减少需要传输的header大小,通讯双方各自cache一份header fields表,既避免了重复header的传输,又减小了需要传输的大小。

  • 服务端推送:服务器除了对最初请求的响应外,服务器还可以额外的向客户端推送资源,而无需客户端明确的请求。

HTTP 与 HTTPS 的区别?

HTTP HTTPS
端口 80 443
安全性 无加密,安全性较差 有加密机制,安全性较高
资源消耗 较少 由于加密处理,资源消耗更多
是否需要证书 不需要 需要
协议 运行在TCP协议之上 运行在SSL协议之上,SSL运行在TCP协议之上

HTTPS 的优缺点?

优点:

  • 安全性:

    • 使用HTTPS协议可认证用户和服务器,确保数据发送到正确的客户机和服务器;

    • HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全,可防止数据在传输过程中不被窃取、改变,确保数据的完整性。

    • HTTPS是现行架构下最安全的解决方案,虽然不是绝对安全,但它大幅增加了中间人攻击的成本。

  • SEO方面:谷歌曾在2014年8月份调整搜索引擎算法,并称“比起同等HTTP网站,采用HTTPS加密的网站在搜索结果中的排名将会更高”。

缺点:

  • 在相同网络环境中,HTTPS 相比 HTTP 无论是响应时间还是耗电量都有大幅度上升。
  • HTTPS 的安全是有范围的,在黑客攻击、服务器劫持等情况下几乎起不到作用。
  • 在现有的证书机制下,中间人攻击依然有可能发生。
  • HTTPS 需要更多的服务器资源,也会导致成本的升高。

讲一讲HTTPS 的原理?

加密流程按图中的序号分为:

  1. 客户端请求 HTTPS 网址,然后连接到 server 的 443 端口 (HTTPS 默认端口,类似于 HTTP 的80端口)。

  2. 采用 HTTPS 协议的服务器必须要有一套数字 CA (Certification Authority)证书。颁发证书的同时会产生一个私钥和公钥。私钥由服务端自己保存,不可泄漏。公钥则是附带在证书的信息中,可以公开的。证书本身也附带一个证书电子签名,这个签名用来验证证书的完整性和真实性,可以防止证书被篡改。

  3. 服务器响应客户端请求,将证书传递给客户端,证书包含公钥和大量其他信息,比如证书颁发机构信息,公司信息和证书有效期等。

  4. 客户端解析证书并对其进行验证。如果证书不是可信机构颁布,或者证书中的域名与实际域名不一致,或者证书已经过期,就会向访问者显示一个警告,由其选择是否还要继续通信。

    如果证书没有问题,客户端就会从服务器证书中取出服务器的公钥A。然后客户端还会生成一个随机码 KEY,并使用公钥A将其加密。

  5. 客户端把加密后的随机码 KEY 发送给服务器,作为后面对称加密的密钥。

  6. 服务器在收到随机码 KEY 之后会使用私钥B将其解密。经过以上这些步骤,客户端和服务器终于建立了安全连接,完美解决了对称加密的密钥泄露问题,接下来就可以用对称加密愉快地进行通信了。

  7. 服务器使用密钥 (随机码 KEY)对数据进行对称加密并发送给客户端,客户端使用相同的密钥 (随机码 KEY)解密数据。

  8. 双方使用对称加密愉快地传输所有数据。

TCP 如何保证可靠性

检验和

通过检验和的方式,接收端可以检测出来数据是否有差错和异常,假如有差错就会直接丢弃TCP段,重新发送。

序列号和确认号机制

序列号的作用不仅仅是应答的作用,有了序列号能够将接收到的数据根据序列号排序,并且去掉重复序列号的数据。

TCP传输的过程中,每次接收方收到数据后,都会对传输方进行确认应答。也就是发送ACK报文,这个ACK报文当中带有对应的确认序列号,告诉发送方,接收到了哪些数据,下一次的数据从哪里发。

超时重发机制

TCP 发送端发送了数据包后会启动一个定时器,如果一定时间没有收到接受端的确认后,将会重新发送该数据包。

对乱序数据包重新排序

从 IP 网络层传输到 TCP 层的数据包可能会乱序,TCP 层会对数据包重新排序再发给应用层。

丢弃重复数据

从 IP 网络层传输到 TCP 层的数据包可能会重复,TCP 层会丢弃重复的数据包。

流量控制

如果主机A 一直向主机B发送数据,不考虑主机B的接受能力,则可能导致主机B的接受缓冲区满了而无法再接受数据,从而会导致大量的数据丢包,引发重传机制。而在重传的过程中,若主机B的接收缓冲区情况仍未好转,则会将大量的时间浪费在重传数据上,降低传送数据的效率。所以引入流量控制机制,主机B通过告诉主机A自己接收缓冲区的大小,来使主机A控制发送的数据量。流量控制与TCP协议报头中的窗口大小有关。

拥塞控制

在数据传输过程中,可能由于网络状态的问题,造成网络拥堵,此时引入拥塞控制机制,在保证TCP可靠性的同时,提高性能。

滑动窗口

滑动窗口既提高了报文传输的效率,也避免了发送方发送过多的数据而导致接收方无法正常处理的异常。

详细讲一下TCP的滑动窗口?

在进行数据传输时,如果传输的数据比较大,就需要拆分为多个数据包进行发送。TCP 协议需要对数据进行确认后,才可以发送下一个数据包。这样一来,就会在等待确认应答包环节浪费时间。

为了避免这种情况,TCP引入了窗口概念。窗口大小指的是不需要等待确认应答包而可以继续发送数据包的最大值。

从上面的图可以看到滑动窗口左边的是已发送并且被确认的分组,滑动窗口右边是还没有轮到的分组。

滑动窗口里面也分为两块,一块是已经发送但是未被确认的分组,另一块是窗口内等待发送的分组。随着已发送的分组不断被确认,窗口内等待发送的分组也会不断被发送。整个窗口就会往右移动,让还没轮到的分组进入窗口内。

可以看到滑动窗口起到了一个限流的作用,也就是说当前滑动窗口的大小决定了当前 TCP 发送包的速率,而滑动窗口的大小取决于拥塞控制窗口流量控制窗口的两者间的最小值。

详细讲一下拥塞控制?

TCP 一共使用了四种算法来实现拥塞控制:

  • 慢开始 (slow-start);

  • 拥塞避免 (congestion avoidance);

  • 快速重传 (fast retransmit);

  • 快速恢复 (fast recovery)。

发送方维持一个叫做拥塞窗口cwnd(congestion window)的状态变量。当cwndssthresh时,改用拥塞避免算法。

慢开始:不要一开始就发送大量的数据,由小到大逐渐增加拥塞窗口的大小。

拥塞避免:拥塞避免算法让拥塞窗口缓慢增长,即每经过一个往返时间RTT就把发送方的拥塞窗口cwnd加1而不是加倍。这样拥塞窗口按线性规律缓慢增长。

快重传:我们可以剔除一些不必要的拥塞报文,提高网络吞吐量。比如接收方在收到一个失序的报文段后就立即发出重复确认,而不要等到自己发送数据时捎带确认。快重传规定:发送方只要一连收到三个重复确认就应当立即重传对方尚未收到的报文段,而不必继续等待设置的重传计时器时间到期。

快恢复:主要是配合快重传。当发送方连续收到三个重复确认时,就执行“乘法减小”算法,把ssthresh门限减半(为了预防网络发生拥塞),但接下来并不执行慢开始算法,因为如果网络出现拥塞的话就不会收到好几个重复的确认,收到三个重复确认说明网络状况还可以。

OSI 的七层模型都有哪些

OSI七层模型一般指开放系统互连参考模型 (Open System Interconnect 简称OSI)是国际标准化组织(ISO)和国际电报电话咨询委员会(CCITT)联合制定的开放系统互连参考模型,为开放式互连信息系统提供了一种功能结构的框架。

  • 应用层:各种应用程序协议,比如 HTTP、HTTPS、FTP、SOCKS 安全套接字协议、DNS 域名系统、GDP 网关发现协议等等。
  • 表示层:加密解密、转换翻译、压缩解压缩,比如 LPP 轻量级表示协议。
  • 会话层:不同机器上的用户建立和管理会话,比如 SSL 安全套接字层协议、TLS 传输层安全协议、RPC 远程过程调用协议等等。
  • 传输层:接受上一层的数据,在必要的时候对数据进行分割,并将这些数据交给网络层,保证这些数据段有效到达对端,比如 TCP 传输控制协议、UDP 数据报协议。
    • TCP:提供面向连接的、可靠的数据传输服务;
    • UDP:提供无连接的、尽最大努力的数据传输服务,但不保证数据传输的可靠性。
  • 网络层:控制子网的运行:逻辑编址、分组传输、路由选择,比如 IP、IPV6、SLIP 等等。
  • 数据链路层:物理寻址,同时将原始比特流转变为逻辑传输路线,比如 XTP 压缩传输协议、PPTP 点对点隧道协议等等。
  • 物理层:机械、电子、定时接口通信信道上的原始比特流传输,比如 IEEE802.2 等等。

说说TCP/IP四层网络模型

TCP/IP分层模型(TCP/IP Layening Model)被称作因特网分层模型(Internet Layering Model)、因特网参考模型(Internet Reference Model)。

TCP/IP协议被组织成四个概念层,其中有三层对应于ISO参考模型中的相应层。ICP/IP协议族并不包含物理层和数据链路层,因此它不能独立完成整个计算机网络系统的功能,必须与许多其他的协议协同工作。

TCP/IP分层模型的四个协议层分别完成以下的功能:

  • 第一层:网络接口层

网络接口层包括用于协作IP数据在已有网络介质上传输的协议。

协议:ARP,RARP

  • 第二层:网间层

网间层对应于OSI七层参考模型的网络层。负责数据的包装、寻址和路由。同时还包含网间控制报文协议(Internet Control Message Protocol,ICMP)用来提供网络诊断信息。

协议:本层包含IP协议、RIP协议(Routing Information Protocol,路由信息协议),ICMP协议。

  • 第三层:传输层

传输层对应于OSI七层参考模型的传输层,它提供两种端到端的通信服务。

其中TCP协议(Transmission Control Protocol)提供可靠的数据流运输服务,UDP协议(UseDatagram Protocol)提供不可靠的用户数据报服务。

  • 第四层:应用层

应用层对应于OSI七层参考模型的应用层和表达层。

因特网的应用层协议包括Finger、Whois、FTP(文件传输协议)、Gopher、HTTP(超文本传输协议)、Telent(远程终端协议)、SMTP(简单邮件传送协议)、IRC(因特网中继会话)、NNTP(网络新闻传输协议)等。

如何实现跨域

当浏览器执行 JS 脚本的时候,会检测脚本要访问的协议、域名、端口号是不是和当前网址一致,如果不一致就是跨域。跨域是不允许的,这种限制叫做浏览器的同源策略,简单点的说法就是浏览器不允许一个源中加载脚本与其他源中的资源进行交互。那么如何实现跨域呢?主要实现方式有三种:JSONP、CORS方式、代理方式。(现在根据更多的时使用代理模式,使用Nginx进行统一代理

JSONP 方式

script、img、iframe、link、video、audio 等带有 src 属性的标签可以跨域请求和执行资源,JSONP 利用这一点“漏洞”实现跨域。

<script>
 var scriptTag = document.createElement('script');
 scriptTag.type = "text/javascript";
 scriptTag.src = "http://10.10.0.101:8899/jsonp?callback=f";
 document.head.appendChild(scriptTag);
</script>

再看下 jQuery 的写法。

$.ajax({
 // 请求域名
 url:'http://10.10.0.101:8899/login',
 // 请求方式
 type:'GET',
 // 数据类型选择 jsonp
 dataType:'jsonp',
 // 回调方法名
 jsonpCallback:'callback',
});
// 回调方法
function callback(response) {
 console.log(response);
}

JSONP 实现跨域很简单但是只支持 GET 请求方式。而且在服务器端接受到 JSONP 请求后需要设置请求头,添加 Access-Control-Allow-Origin属性,属性值为 * ,表示允许所有域名访问,这样浏览器才会正常解析,否则会报 406 错误。

response.setHeader("Access-Control-Allow-Origin", "*");

CORS 方式

CORS-Origin Resource Sharing)即跨域资源共享,需要浏览器和服务器同时支持,这种请求方式分为简单请求和非简单请求。

当浏览器发出的 XMLHttpRequest 请求的请求方式是 POST 或者 GET,请求头中只包含 Accept、Accept-Language、Content-Language、Last-Event-ID、Content-Type(applicationx-www-form-urlencoded、multipart/form-data、text/plain)时那么这个请求就是一个简单请求。

对于简单的请求,浏览器会在请求头中添加 Origin 属性,标明本次请求来自哪个源(协议 + 域名 + 端口)。

GET
// 标明本次请求来自哪个源(协议+域名+端口)
Origin: http://127.0.0.1:8080
// IP
Host: 127.0.0.1:8080
// 长连接
Connection: keep-alive
Content-Type: text/plain

如果 Origin 标明的域名在服务器许可范围内,那么服务器就会给出响应:

// 该值上文提到过,表示允许浏览器指定的域名访问,要么为浏览器传入的 origin,要么为 * 表示
所有域名都可以访问
 Access-Control-Allow-Origin: http://127.0.0.1:8080
 // 表示服务器是否同意浏览器发送 cookie
 Access-Control-Allow-Credentials: true
 // 指定 XMLHttpRequest#getResponseHeader() 方法可以获取到的字段
 Access-Control-Expose-Headers: xxx
 Content-Type: text/html; charset=utf-8

Access-Control-Allow-Credentials: true表示服务器同意浏览器发送 cookie,另外浏览器也需要设置支持发送 cookie,否则就算服务器支持浏览器也不会发送。

var xhr = new XMLHttpRequest();
// 设置发送的请求是否带 cookie
xhr.withCredentials = true;
xhr.open('post', 'http://10.10.0.101:8899/login', true);
xhr.setRequestHeader('Content-Type', 'text/plain');

另外一种是非简单请求,请求方式是 PUT 或 DELETE,或者请求头中添加了 Content-Type:application/json 属性和属性值的请求。

这种请求在浏览器正式发出 XMLHttpRequest 请求前会先发送一个预检 HTTP 请求,询问服务器当前网页的域名是否在服务器的许可名单之中,只有得到服务器的肯定后才会正式发出通信请求。

预检请求的头信息:

// 预检请求的请求方式是 OPTIONS
OPTIONS
// 标明本次请求来自哪个源(协议+域名+端口)
Origin: http://127.0.0.1:8080
// 标明接下来的 CORS 请求要使用的请求方式
Access-Control-Request-Method: PUT
// 标明接下来的 CORS 请求要附加发送的头信息属性
Access-Control-Request-Headers: X-Custom-Header
// IP
Host: 127.0.0.1:8080
// 长连接
Connection: keep-alive

如果服务器回应预检请求的响应头中没有任何 CORS 相关的头信息的话表示不支持跨域,如果允许跨域就会做出响应,响应头信息如下:

HTTP/1.1 200 OK
// 该值上文提到过,表示允许浏览器指定的域名访问,要么为浏览器传入的 origin,要么为 * 表示所
有域名都可以访问
Access-Control-Allow-Origin:http://127.0.0.1:8080
// 服务器支持的所有跨域请求方式,为了防止浏览器发起多次预检请求把所有的请求方式返回给浏览器
Access-Control-Allow-Methods: GET, POST, PUT
// 服务器支持预检请求头信息中的 Access-Control-Request-Headers 属性值
Access-Control-Allow-Headers: X-Custom-Header
// 服务器同意浏览器发送 cookie
Access-Control-Allow-Credentials: true
// 指定预检请求的有效期是 20 天,期间不必再次发送另一个预检请求
Access-Control-Max-Age:1728000
Content-Type: text/html; charset=utf-8
Keep-Alive: timeout=2, max=100
// 长连接
Connection: Keep-Alive
Content-Type: text/plain

接着浏览器会像简单请求一样,发送一个 CORS 请求,请求头中一定包含 Origin 属性,服务器的响应头中也一定得包含 Access-Control-Allow-Origin 属性。

代理方式(最优方案)

跨域限制是浏览器的同源策略导致的,使用 nginx 当做服务器访问别的服务的 HTTP 接口是不需要执行 JS 脚步不存在同源策略限制的,所以可以利用 Nginx 创建一个代理服务器,这个代理服务器的域名跟浏览器要访问的域名一致,然后通过这个代理服务器修改 cookie 中的域名为要访问的 HTTP接口的域名,通过反向代理实现跨域。

Nginx 的配置信息:

server {
   # 代理服务器的端口
   listen 88;
   # 代理服务器的域名
   server_name http://127.0.0.1;
   location / {
      # 反向代理服务器的域名+端口
      proxy_pass http://127.0.0.2:89;
      # 修改cookie里域名
      proxy_cookie_domain http://127.0.0.2 http://127.0.0.1;
      index index.html index.htm;
      # 设置当前代理服务器允许浏览器跨域
      add_header Access-Control-Allow-Origin http://127.0.0.1;
      # 设置当前代理服务器允许浏览器发送 cookie
      add_header Access-Control-Allow-Credentials true;
   }
}

前端代码:(正常发送http请求即可)

var xhr = new XMLHttpRequest();
// 设置浏览器允许发送 cookie
xhr.withCredentials = true;
// 访问 nginx 代理服务器
xhr.open('get', 'http://127.0.0.1:88', true);
xhr.send();

说说TCP三次握手和四次挥手的全过程

三次握手

  • 第一次握手:客户端请求建立连接,向服务端发送一个同步报文(SYN=1),同时选择一个随机数 seq = x 作为初始序列号,并进入SYN_SENT状态,等待服务器确认。

  • 第二次握手:服务端收到连接请求报文后,如果同意建立连接,则向客户端发送同步确认报文(SYN=1,ACK=1),确认号为 ack = x + 1,同时选择一个随机数 seq = y 作为初始序列号,此时服务器进入SYN_RECV状态。

  • 第三次握手:客户端收到服务端的确认后,向服务端发送一个确认报文(ACK=1),确认号为 ack = y + 1,序列号为 seq = x + 1,客户端和服务器进入ESTABLISHED状态,完成三次握手。

理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连接之前,TCP 连接都将被一直保持下去。

四次挥手

  • 第一次挥手:客户端向服务端发送连接释放报文(FIN=1,ACK=1),主动关闭连接,同时等待服务端的确认。

    • 序列号 seq = u,即客户端上次发送的报文的最后一个字节的序号 + 1
    • 确认号 ack = k, 即服务端上次发送的报文的最后一个字节的序号 + 1
  • 第二次挥手:服务端收到连接释放报文后,立即发出确认报文(ACK=1),序列号 seq = k,确认号 ack = u + 1。

    这时 TCP 连接处于半关闭状态,即客户端到服务端的连接已经释放了,但是服务端到客户端的连接还未释放。这表示客户端已经没有数据发送了,但是服务端可能还要给客户端发送数据。

  • 第三次挥手:服务端向客户端发送连接释放报文(FIN=1,ACK=1),主动关闭连接,同时等待 A 的确认。

    • 序列号 seq = w,即服务端上次发送的报文的最后一个字节的序号 + 1。
    • 确认号 ack = u + 1,与第二次挥手相同,因为这段时间客户端没有发送数据
  • 第四次挥手:客户端收到服务端的连接释放报文后,立即发出确认报文(ACK=1),序列号 seq = u + 1,确认号为 ack = w + 1。

此时,客户端就进入了 TIME-WAIT 状态。注意此时客户端到 TCP 连接还没有释放,必须经过 2*MSL(最长报文段寿命)的时间后,才进入 CLOSED 状态。而服务端只要收到客户端发出的确认,就立即进入 CLOSED 状态。可以看到,服务端结束 TCP 连接的时间要比客户端早一些。

为什么需要三次握手,而不是两次?

主要有三个原因:

  1. 防止已过期的连接请求报文突然又传送到服务器,因而产生错误和资源浪费。

    在双方两次握手即可建立连接的情况下,假设客户端发送 A 报文段请求建立连接,由于网络原因造成 A 暂时无法到达服务器,服务器接收不到请求报文段就不会返回确认报文段。

    客户端在长时间得不到应答的情况下重新发送请求报文段 B,这次 B 顺利到达服务器,服务器随即返回确认报文并进入 ESTABLISHED 状态,客户端在收到 确认报文后也进入 ESTABLISHED 状态,双方建立连接并传输数据,之后正常断开连接。

    此时姗姗来迟的 A 报文段才到达服务器,服务器随即返回确认报文并进入 ESTABLISHED 状态,但是已经进入 CLOSED 状态的客户端无法再接受确认报文段,更无法进入 ESTABLISHED 状态,这将导致服务器长时间单方面等待,造成资源浪费。

  2. 三次握手才能让双方均确认自己和对方的发送和接收能力都正常。

    第一次握手:客户端只是发送处请求报文段,什么都无法确认,而服务器可以确认自己的接收能力和对方的发送能力正常;

    第二次握手:客户端可以确认自己发送能力和接收能力正常,对方发送能力和接收能力正常;

    第三次握手:服务器可以确认自己发送能力和接收能力正常,对方发送能力和接收能力正常;

    可见三次握手才能让双方都确认自己和对方的发送和接收能力全部正常,这样就可以愉快地进行通信了。

  3. 告知对方自己的初始序号值,并确认收到对方的初始序号值。

    TCP 实现了可靠的数据传输,原因之一就是 TCP 报文段中维护了序号字段和确认序号字段,通过这两个字段双方都可以知道在自己发出的数据中,哪些是已经被对方确认接收的。这两个字段的值会在初始序号值得基础递增,如果是两次握手,只有发起方的初始序号可以得到确认,而另一方的初始序号则得不到确认。

为什么要三次握手,而不是四次?

因为三次握手已经可以确认双方的发送接收能力正常,双方都知道彼此已经准备好,而且也可以完成对双方初始序号值得确认,也就无需再第四次握手了。

  • 第一次握手:服务端确认“自己收、客户端发”报文功能正常。
  • 第二次握手:客户端确认“自己发、自己收、服务端收、客户端发”报文功能正常,客户端认为连接已建立。
  • 第三次握手:服务端确认“自己发、客户端收”报文功能正常,此时双方均建立连接,可以正常通信。

为什么连接的时候是三次握手,关闭的时候却是四次握手?

服务器在收到客户端的 FIN 报文段后,可能还有一些数据要传输,所以不能马上关闭连接,但是会做出应答,返回 ACK 报文段.

接下来可能会继续发送数据,在数据发送完后,服务器会向客户单发送 FIN 报文,表示数据已经发送完毕,请求关闭连接。服务器的ACK和FIN一般都会分开发送,从而导致多了一次,因此一共需要四次挥手。

为什么客户端的 TIME-WAIT 状态必须等待 2MSL ?

主要有两个原因:

  1. 确保 ACK 报文能够到达服务端,从而使服务端正常关闭连接。

第四次挥手时,客户端第四次挥手的 ACK 报文不一定会到达服务端。服务端会超时重传 FIN/ACK 报文,此时如果客户端已经断开了连接,那么就无法响应服务端的二次请求,这样服务端迟迟收不到 FIN/ACK 报文的确认,就无法正常断开连接。

MSL 是报文段在网络上存活的最长时间。客户端等待 2MSL 时间,即「客户端 ACK 报文 1MSL 超时 + 服务端 FIN 报文 1MSL 传输」,就能够收到服务端重传的 FIN/ACK 报文,然后客户端重传一次 ACK 报文,并重新启动 2MSL 计时器。如此保证服务端能够正常关闭。

如果服务端重发的 FIN 没有成功地在 2MSL 时间里传给客户端,服务端则会继续超时重试直到断开连接。

  1. 防止已失效的连接请求报文段出现在之后的连接中。

TCP 要求在 2MSL 内不使用相同的序列号。客户端在发送完最后一个 ACK 报文段后,再经过时间 2MSL,就可以保证本连接持续的时间内产生的所有报文段都从网络中消失。这样就可以使下一个连接中不会出现这种旧的连接请求报文段。或者即使收到这些过时的报文,也可以不处理它。

如果已经建立了连接,但是客户端出现故障了怎么办?

或者说,如果三次握手阶段、四次挥手阶段的包丢失了怎么办?如“服务端重发 FIN丢失”的问题。

简而言之,通过定时器 + 超时重试机制,尝试获取确认,直到最后会自动断开连接。

具体而言,TCP 设有一个保活计时器。服务器每收到一次客户端的数据,都会重新复位这个计时器,时间通常是设置为 2 小时。若 2 小时还没有收到客户端的任何数据,服务器就开始重试:每隔 75 分钟发送一个探测报文段,若一连发送 10 个探测报文后客户端依然没有回应,那么服务器就认为连接已经断开了。

TIME-WAIT 状态过多会产生什么后果?怎样处理?

从服务器来讲,短时间内关闭了大量的Client连接,就会造成服务器上出现大量的TIME_WAIT连接,严重消耗着服务器的资源,此时部分客户端就会显示连接不上。

从客户端来讲,客户端TIME_WAIT过多,就会导致端口资源被占用,因为端口就65536个,被占满就会导致无法创建新的连接。

解决办法:

  • 服务器可以设置 SO_REUSEADDR 套接字选项来避免 TIME_WAIT状态,此套接字选项告诉内核,即使此端口正忙(处于
    TIME_WAIT状态),也请继续并重用它。

  • 调整系统内核参数,修改/etc/sysctl.conf文件,即修改net.ipv4.tcp_tw_reuse 和 tcp_timestamps

    net.ipv4.tcp_tw_reuse = 1 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
    net.ipv4.tcp_tw_recycle = 1 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。
  • 强制关闭,发送 RST 包越过TIME_WAIT状态,直接进入CLOSED状态。

TIME_WAIT 是服务器端的状态?还是客户端的状态?

TIME_WAIT 是主动断开连接的一方会进入的状态,一般情况下,都是客户端所处的状态;服务器端一般设置不主动关闭连接。

TIME_WAIT 需要等待 2MSL,在大量短连接的情况下,TIME_WAIT会太多,这也会消耗很多系统资源。对于服务器来说,在 HTTP 协议里指定 KeepAlive(浏览器重用一个 TCP 连接来处理多个 HTTP 请求),由浏览器来主动断开连接,可以一定程度上减少服务器的这个问题。

什么是 SYN洪泛攻击?如何防范?

SYN洪泛攻击属于 DOS 攻击的一种,它利用 TCP 协议缺陷,通过发送大量的半连接请求,耗费 CPU 和内存资源。

原理:

  • 在三次握手过程中,服务器发送 [SYN/ACK] 包(第二个包)之后、收到客户端的 [ACK] 包(第三个包)之前的 TCP 连接称为半连接(half-open connect),此时服务器处于 SYN_RECV(等待客户端响应)状态。如果接收到客户端的 [ACK],则 TCP 连接成功,如果未接受到,则会不断重发请求直至成功。
  • SYN 攻击的攻击者在短时间内伪造大量不存在的 IP 地址,向服务器不断地发送 [SYN] 包,服务器回复 [SYN/ACK] 包,并等待客户的确认。由于源地址是不存在的,服务器需要不断的重发直至超时。
  • 这些伪造的 [SYN] 包将长时间占用未连接队列,影响了正常的 SYN,导致目标系统运行缓慢、网络堵塞甚至系统瘫痪。

检测:

当在服务器上看到大量的半连接状态时,特别是源 IP 地址是随机的,基本上可以断定这是一次 SYN 攻击。

防范:

  • 通过防火墙、路由器等过滤网关防护。
  • 通过加固 TCP/IP 协议栈防范,如增加最大半连接数,缩短超时时间。
  • SYN cookies技术。SYN Cookies 是对 TCP 服务器端的三次握手做一些修改,专门用来防范 SYN 洪泛攻击的一种手段。

三次握手连接阶段,最后一次ACK包丢失,会发生什么?

服务端:

  • 第三次的ACK在网络中丢失,那么服务端该TCP连接的状态为SYN_RECV,并且会根据 TCP的超时重传机制,会等待3秒、6秒、12秒后重新发送SYN+ACK包,以便客户端重新发送ACK包。
  • 如果重发指定次数之后,仍然未收到 客户端的ACK应答,那么一段时间后,服务端自动关闭这个连接。

客户端:

客户端认为这个连接已经建立,如果客户端向服务端发送数据,服务端将以RST包(Reset,标示复位,用于异常的关闭连接)响应。此时,客户端知道第三次握手失败。

说说域名解析详细过程

  1. 域名解析(域名 www.baidu.com 变为 ip 地址)。

浏览器搜索自己的DNS缓存(维护一张域名与IP的对应表);若没有,则搜索操作系统的DNS缓存(维护一张域名与IP的对应表);若没有,则搜索操作系统的hosts文件(维护一张域名与IP的对应表)。

若都没有,则找 tcp/ip 参数中设置的首选 dns 服务器,即本地 dns 服务器(递归查询),本地域名服务器查询自己的dns缓存,如果没有,则进行迭代查询。将本地dns服务器将IP返回给操作系统,同时缓存IP。

  1. 发起 tcp 的三次握手,建立 tcp 连接。浏览器会以一个随机端口(1024-65535)向服务端的 web 程序 80 端口发起 tcp 的连接。

  2. 建立 tcp 连接后发起 http 请求。

  3. 服务器响应 http 请求,客户端得到 html 代码。服务器 web 应用程序收到 http 请求后,就开始处理请求,处理之后就返回给浏览器 html 文件。

  4. 浏览器解析 html 代码,并请求 html 中的资源。

  5. 浏览器对页面进行渲染,并呈现给用户。

什么是 Cookie

HTTP Cookie(也叫 Web Cookie或浏览器 Cookie)是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。通常,它用于告知服务端两个请求是否来自同一浏览器,如保持用户的登录状态。Cookie 使基于无状态的 HTTP 协议记录稳定的状态信息成为了可能。

Cookie 主要用于以下三个方面:

  • 会话状态管理(如用户登录状态、购物车、游戏分数或其它需要记录的信息)
  • 个性化设置(如用户自定义设置、主题等)
  • 浏览器行为跟踪(如跟踪分析用户行为等)

什么是 Session

Session 代表着服务器和客户端一次会话的过程。Session 对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当客户端关闭会话,或者 Session 超时失效时会话结束。

Cookie和Session的区别?

  • 作用范围不同,Cookie 保存在客户端(浏览器),Session 保存在服务器端。
  • 存取方式的不同,Cookie 只能保存 ASCII,Session 可以存任意数据类型,一般情况下我们可以在 Session 中保持一些常用变量信息,比如说 UserId 等。
  • 有效期不同,Cookie 可设置为长时间保持,比如我们经常使用的默认登录功能,Session 一般失效时间较短,客户端关闭或者 Session 超时都会失效。
  • 隐私策略不同,Cookie 存储在客户端,比较容易遭到不法获取,早期有人将用户的登录名和密码存储在 Cookie 中导致信息被窃取;Session 存储在服务端,安全性相对 Cookie 要好一些。
  • 存储大小不同, 单个 Cookie 保存的数据不能超过 4K,Session 可存储数据远高于 Cookie。

用户第一次请求服务器的时候,服务器根据用户提交的相关信息,创建对应的 Session ,请求返回时将此 Session 的唯一标识信息 SessionID 返回给浏览器,浏览器接收到服务器返回的 SessionID 信息后,会将此信息存入到 Cookie 中,同时 Cookie 记录此 SessionID 属于哪个域名。

当用户第二次访问服务器的时候,请求会自动判断此域名下是否存在 Cookie 信息,如果存在自动将 Cookie 信息也发送给服务端,服务端会从 Cookie 中获取 SessionID,再根据 SessionID 查找对应的 Session 信息,如果没有找到说明用户没有登录或者登录失效,如果找到 Session 证明用户已经登录可执行后面操作。

根据以上流程可知,SessionID 是连接 Cookie 和 Session 的一道桥梁,大部分系统也是根据此原理来验证用户登录状态。

如何考虑分布式 Session 问题?

在互联网公司为了可以支撑更大的流量,后端往往需要多台服务器共同来支撑前端用户请求,那如果用户在 A 服务器登录了,第二次请求跑到服务 B 就会出现登录失效问题。

分布式 Session 一般会有以下几种解决方案:

  • 客户端存储:直接将信息存储在cookie中,cookie是存储在客户端上的一小段数据,客户端通过http协议和服务器进行cookie交互,通常用来存储一些不敏感信息
  • Nginx ip_hash 策略:服务端使用 Nginx 代理,每个请求按访问 IP 的 hash 分配,这样来自同一 IP 固定访问一个后台服务器,避免了在服务器 A 创建 Session,第二次分发到服务器 B 的现象。
  • Session 复制:任何一个服务器上的 Session 发生改变(增删改),该节点会把这个 Session 的所有内容序列化,然后广播给所有其它节点。
  • 共享 Session:服务端无状态话,将用户的 Session 等信息使用缓存中间件(如Redis)来统一管理,保障分发到每一个服务器的响应结果都一致。

建议采用共享 Session的方案。

什么是DDos攻击?

DDos全称Distributed Denial of Service,分布式拒绝服务攻击。最基本的DOS攻击过程如下:

  1. 客户端向服务端发送请求链接数据包。
  2. 服务端向客户端发送确认数据包。
  3. 客户端不向服务端发送确认数据包,服务器一直等待来自客户端的确认

DDoS则是采用分布式的方法,通过在网络上占领多台“肉鸡”,用多台计算机发起攻击。

DOS攻击现在基本没啥作用了,因为服务器的性能都很好,而且是多台服务器共同作用,1V1的模式黑客无法占上风。

对于DDOS攻击,预防方法有:

  • 减少SYN timeout时间。在握手的第三步,服务器会等待30秒-120秒的时间,减少这个等待时间就能释放更多的资源。
  • 限制同时打开的SYN半连接数目。

什么是XSS攻击?

XSS也称 cross-site scripting,跨站脚本。这种攻击是由于服务器将攻击者存储的数据原原本本地显示给其他用户所致的。比如一个存在XSS漏洞的论坛,用户发帖时就可以引入带有<script>标签的代码,导致恶意代码的执行。

预防措施有:

  • 前端:过滤。
  • 后端:转义,比如go自带的处理器就具有转义功能。

SQL注入是什么,如何避免SQL注入?

SQL 注入就是在用户输入的字符串中加入 SQL 语句,如果在设计不良的程序中忽略了检查,那么这些注入进去的 SQL 语句就会被数据库服务器误认为是正常的 SQL 语句而运行,攻击者就可以执行计划外的命令或访问未被授权的数据。

SQL注入的原理主要有以下4点

  • 恶意拼接查询
  • 利用注释执行非法命令
  • 传入非法参数
  • 添加额外条件

避免SQL注入的一些方法:

  • 限制数据库权限,给用户提供仅仅能够满足其工作的最低权限。
  • 对进入数据库的特殊字符(’”\尖括号&*;等)转义处理。
  • 提供参数化查询接口,不要直接使用原生SQL。

负载均衡算法有哪些?

多台服务器以对称的方式组成一个服务器集合,每台服务器都具有等价的地位,能互相分担负载。

  • 轮询法:将请求按照顺序轮流的分配到服务器上。大锅饭,不能发挥某些高性能服务器的优势。
  • 随机法:随机获取一台,和轮询类似。
  • 哈希法:通过ip地址哈希化来确定要选择的服务器编号。好处是,每次客户端访问的服务器都是同一个服务器,能很好地利用session或者cookie。
  • 加权轮询:根据服务器性能不同加权。

文章作者: 程序猿洞晓
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 程序猿洞晓 !
评论
 上一篇
Java问答知识总结篇-ElasticSearch Java问答知识总结篇-ElasticSearch
以问答的方式构建Java知识体系,另外在问答中提供技术博客的支撑,更具体的解析和剖析内部深度知识点,做一个有深度的问答总结集。内容包括Java基础知识、JVM、Spring、Spring Cloud && Spring Cloud Alibaba、Mybatis、Spring Boot、Mybatis、Redis、MySQL等等。
2022-09-21
下一篇 
Java问答知识总结篇-分布式 Java问答知识总结篇-分布式
以问答的方式构建Java知识体系,另外在问答中提供技术博客的支撑,更具体的解析和剖析内部深度知识点,做一个有深度的问答总结集。内容包括Java基础知识、JVM、Spring、Spring Cloud && Spring Cloud Alibaba、Mybatis、Spring Boot、Mybatis、Redis、MySQL等等。
2022-09-21
  目录