目录
HTTP
-
通用头部
-
请求方法
-
GET请求会向数据库发索取数据的请求,从而来获取信息,该请求就像数据库的select操作一样,只是用来查询一下数据,不会修改、增加数据,不会影响资源的内容,即该请求不会产生副作用。无论进行多少次操作,结果都是一样的。
-
与GET不同的是,PUT请求是向服务器端发送数据的,从而改变信息,该请求就像数据库的update操作一样,用来修改数据的内容,但是不会增加数据的种类等,也就是说无论进行多少次PUT操作,其结果并没有不同。
-
POST请求同PUT请求类似,都是向服务器端发送数据的,但是该请求会改变数据的种类等资源,就像数据库的insert操作一样,会创建新的内容。几乎目前所有的提交操作都是用POST请求的。
-
DELETE请求顾名思义,就是用来删除某一个资源的,该请求就像数据库的delete操作。
-
Get与Post区别
-
GET一般用于获取/查询资源信息,而POST一般用于更新资源信息
-
GET请求的数据会附在URL之后(就是把数据放置在HTTP协议头中),以?分割URL和传输数据,参数之间以&相连;POST把提交的数据则放置在是HTTP包的包体中
-
POST的安全性要比GET的安全性高
-
-
状态码
-
2xx (3种)
- 200 OK:表示从客户端发送给服务器的请求被正常处理并返回;
- 204 No Content:表示客户端发送给客户端的请求得到了成功处理,但在返回的响应报文中不含实体的主体部分(没有资源可以返回);
- 206 Patial Content:表示客户端进行了范围请求,并且服务器成功执行了这部分的GET请求,响应报文中包含由Content-Range指定范围的实体内容。
-
3xx (5种)
-
301 Moved Permanently:永久性重定向,表示请求的资源被分配了新的URL,之后应使用更改的URL;
-
302 Found:临时性重定向,表示请求的资源被分配了新的URL,希望本次访问使用新的URL;
301与302的区别:前者是永久移动,后者是临时移动(之后可能还会更改URL)
-
303 See Other:表示请求的资源被分配了新的URL,应使用GET方法定向获取请求的资源;
302与303的区别:后者明确表示客户端应当采用GET方式获取资源
-
304 Not Modified:表示客户端发送附带条件(是指采用GET方法的请求报文中包含if-Match、If-Modified-Since、If-None-Match、If-Range、If-Unmodified-Since中任一首部)的请求时,服务器端允许访问资源,但是请求为满足条件的情况下返回改状态码;
-
307 Temporary Redirect:临时重定向,与303有着相同的含义,307会遵照浏览器标准不会从POST变成GET;(不同浏览器可能会出现不同的情况);
-
-
4xx (4种)
- 400 Bad Request:表示请求报文中存在语法错误;
- 401 Unauthorized:未经许可,需要通过HTTP认证;
- 403 Forbidden:服务器拒绝该次访问(访问权限出现问题)
- 404 Not Found:表示服务器上无法找到请求的资源,除此之外,也可以在服务器拒绝请求但不想给拒绝原因时使用;
-
5xx (2种)
- 500 Inter Server Error:表示服务器在执行请求时发生了错误,也有可能是web应用存在的bug或某些临时的错误时;
- 503 Server Unavailable:表示服务器暂时处于超负载或正在进行停机维护,无法处理请求;
-
-
-
请求/响应头部
-
请求/响应实体
Cookie、Session和Token
看完这篇 Session、Cookie、Token,和面试官扯皮就没问题了
-
HTTP 协议是一种
无状态协议
,即每次服务端接收到客户端的请求时,都是一个全新的请求,服务器并不知道客户端的历史请求记录;Session 和 Cookie 的主要目的就是为了弥补 HTTP 的无状态特性。 -
Session
- 定义:客户端请求服务端,服务端会为这次请求开辟一块
内存空间
,这个对象便是 Session 对象,存储结构为ConcurrentHashMap
。Session 弥补了 HTTP 无状态特性,服务器可以利用 Session 存储客户端在同一个会话期间的一些操作记录。 - Session 如何判断是否是同一会话:
- 服务器第一次接收到请求时,开辟了一块 Session 空间(创建了Session对象),同时生成一个 sessionId ,并通过响应头的 **Set-Cookie:JSESSIONID=XXXXXXX **命令,向客户端发送要求设置 Cookie 的响应; 客户端收到响应后,在本机客户端设置了一个 **JSESSIONID=XXXXXXX **的 Cookie 信息,该 Cookie 的过期时间为浏览器会话结束
- 接下来客户端每次向同一个网站发送请求时,请求头都会带上该 Cookie信息(包含 sessionId ), 然后,服务器通过读取请求头中的 Cookie 信息,获取名称为 JSESSIONID 的值,得到此次请求的 sessionId。
- 缺点:Session 机制有个缺点,比如 A 服务器存储了 Session,就是做了负载均衡后,假如一段时间内 A 的访问量激增,会转发到 B 进行访问,但是 B 服务器并没有存储 A 的 Session,会导致 Session 的失效。
- 定义:客户端请求服务端,服务端会为这次请求开辟一块
-
Cookie
- 定义:HTTP 协议中的 Cookie 包括 Web Cookie 和浏览器 Cookie,它是服务器发送到 Web 浏览器的一小块数据。服务器发送到浏览器的 Cookie,浏览器会进行存储,并与下一个请求一起发送到服务器。通常,它用于判断两个请求是否来自于同一个浏览器,例如用户保持登录状态。
- HTTP Cookie 机制是 HTTP 协议无状态的一种补充和改良
- 目的:
- 会话管理:登陆、购物车、游戏得分或者服务器应该记住的其他内容
- 个性化:用户偏好、主题或者其他设置
- 追踪:记录和分析用户行为
- 创建:
- 当接收到客户端发出的 HTTP 请求时,服务器可以发送带有响应的
Set-Cookie
标头,Cookie 通常由浏览器存储,然后将 Cookie 与 HTTP 标头一同向服务器发出请求。
- 当接收到客户端发出的 HTTP 请求时,服务器可以发送带有响应的
- Set-Cookie 和 Cookie 标头
Set-Cookie
HTTP 响应标头将 cookie 从服务器发送到用户代理,此标头告诉客户端存储 Cookie,之后,随着对服务器的每个新请求,浏览器将使用 Cookie 头将所有以前存储的 Cookie 发送回服务器。- 有两种类型的 Cookies,一种是 Session Cookies,一种是 Persistent Cookies,如果 Cookie 不包含到期日期,则将其视为会话 Cookie。会话 Cookie 存储在内存中,永远不会写入磁盘,当浏览器关闭时,此后 Cookie 将永久丢失。如果 Cookie 包含有效期 ,则将其视为持久性 Cookie。在到期指定的日期,Cookie 将从磁盘中删除。
- 会话 Cookies:
- 会话 Cookie 有个特征,客户端关闭时 Cookie 会删除,因为它没有指定
Expires
或Max-Age
指令。但是,Web 浏览器可能会使用会话还原,这会使大多数会话 Cookie 保持永久状态,就像从未关闭过浏览器一样
- 会话 Cookie 有个特征,客户端关闭时 Cookie 会删除,因为它没有指定
- 永久性 Cookies
- 永久性 Cookie 不会在客户端关闭时过期,而是在
特定日期(Expires)
或特定时间长度(Max-Age)
外过期 Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;
- 永久性 Cookie 不会在客户端关闭时过期,而是在
- Cookie 的 Secure 和 HttpOnly 标记
- 安全的 Cookie 需要经过 HTTPS 协议通过加密的方式发送到服务器。即使是安全的,也不应该将敏感信息存储在cookie 中,因为它们本质上是不安全的,并且此标志不能提供真正的保护。
- HttpOnly 的作用:
- 会话 Cookie 中缺少 HttpOnly 属性会导致攻击者可以通过程序(JS脚本、Applet等)获取到用户的 Cookie 信息,造成用户 Cookie 信息泄露,增加攻击者的跨站脚本攻击威胁。
- HttpOnly 是微软对 Cookie 做的扩展,该值指定 Cookie 是否可通过客户端脚本访问。
- 如果在 Cookie 中没有设置 HttpOnly 属性为 true,可能导致 Cookie 被窃取。窃取的 Cookie 可以包含标识站点用户的敏感信息,如 ASP.NET 会话 ID 或 Forms 身份验证票证,攻击者可以重播窃取的 Cookie,以便伪装成用户或获取敏感信息,进行跨站脚本攻击等。
- Cookie 的作用域
Domain
和Path
标识定义了 Cookie 的作用域:即 Cookie 应该发送给哪些 URL。Domain
标识指定了哪些主机可以接受 Cookie。如果不指定,默认为当前主机(不包含子域名)。如果指定了Domain
,则一般包含子域名。
-
JSON Web Token
JSON Web Token ,简称 JWT
,它和Session
都可以为网站提供用户的身份认证,它们既可以对用户进行身份验证,也可以用来在用户单击进入不同页面时以及登陆网站或应用程序后进行身份验证。如果没有这两者,那你可能需要在每个页面切换时都需要进行登录了。因为 HTTP 是一个无状态的协议。这也就意味着当你访问某个网页,然后单击同一站点上的另一个页面时,服务器的内存中将不会记住你之前的操作。- JWT 和 Session Cookies 就是用来处理在不同页面之间切换,保存用户登录信息的机制。也就是说,这两种技术都是用来保存你的登录状态,能够让你在浏览任意受密码保护的网站。通过在每次产生新的请求时对用户数据进行身份验证来解决此问题.它们能够支持你在发送不同请求之间,记录并验证你的登录状态的一种机制
- 定义:
- Json Web Token 的简称就是 JWT,通常可以称为 Json 令牌。它是RFC 7519 中定义的用于安全的将信息作为 Json 对象进行传输的一种形式。JWT 中存储的信息是经过数字签名的,因此可以被信任和理解。可以使用 HMAC 算法或使用 RSA/ECDSA 的公用/专用密钥对 JWT 进行签名。
- 作用:
- 认证(Authorization):这是使用 JWT 最常见的一种情况,一旦用户登录,后面每个请求都会包含 JWT,从而允许用户访问该令牌所允许的路由、服务和资源。单点登录是当今广泛使用 JWT 的一项功能,因为它的开销很小。
- 信息交换(Information Exchange):JWT 是能够安全传输信息的一种方式。通过使用公钥/私钥对 JWT 进行签名认证。此外,由于签名是使用 head 和 payload 计算的,因此你还可以验证内容是否遭到篡改。
- 格式:
- JWT 主要由三部分组成,每个部分用
.
进行分割,各个部分分别是Header
:Header 是 JWT 的标头,它通常由两部分组成:令牌的类型(即 JWT)
和使用的签名算法
,指定类型和签名算法后,Json 块被Base64Url
编码形成 JWT 的第一部分。Payload
:Token 的第二部分是Payload
,Payload 中包含一个声明。声明是有关实体(通常是用户)和其他数据的声明。共有三种类型的声明:registered, public 和 private 声明。Signature
:JWT 的第三部分是一个签证信息,这个签证信息由三部分组成:header (base64后的)
、payload (base64后的)
、secret
- 下面是一个完整的 JWT 示例,它对 header 和 payload 进行编码,然后使用 signature 进行签名:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
- JWT 主要由三部分组成,每个部分用
- JWT 和 Session Cookies 的不同:
- 密码签名:JWT 具有加密签名,而 Session Cookies 则没有。
- JSON 是无状态的:JWT 是
无状态
的,因为声明被存储在客户端
,而不是服务端内存中。身份验证可以在本地
进行,而不是在请求必须通过服务器数据库或类似位置中进行。 这意味着可以对用户进行多次身份验证,而无需与站点或应用程序的数据库进行通信,也无需在此过程中消耗大量资源。 - 可扩展性:Session Cookies 是存储在服务器内存中,这就意味着如果网站或者应用很大的情况下会耗费大量的资源。由于 JWT 是无状态的,在许多情况下,它们可以节省服务器资源。因此 JWT 要比 Session Cookies 具有更强的
可扩展性
。 - JWT 支持跨域认证:Session Cookies 只能用在单个节点的域或者它的子域中有效。如果它们尝试通过第三个节点访问,就会被禁止。如果你希望自己的网站和其他站点建立安全连接时,这是一个问题。使用 JWT 可以解决这个问题,使用 JWT 能够通过多个节点进行用户认证,也就是我们常说的跨域认证。
- JWT 和 Session Cookies 的选型:
- 对于只需要登录用户并访问存储在站点数据库中的一些信息的中小型网站来说,Session Cookies 通常就能满足。
- 如果你有企业级站点,应用程序或附近的站点,并且需要处理大量的请求,尤其是第三方或很多第三方(包括位于不同域的API),则 JWT 显然更适合。
浏览器缓存
首先缓存是为了在前后端http交互中提升效率的,浏览器每次发起请求,都要先看浏览器中有没有缓存以及有没有失效,再决定是否继续向服务器提交申请。
缓存分为强制缓存和协商缓存,通过Http头部区分。
强制缓存优先于协商缓存进行,若强制缓存生效则直接使用缓存,若不生效则进行协商缓存,协商缓存由服务器决定是否使用缓存,若协商缓存失效,那么代表该请求的缓存失效,重新获取请求结果,再存入浏览器缓存中;生效则返回304,继续使用缓存
- 目的
前后端的http交互中,使用缓存能很大程度上的提升效率,而且基本上对性能有要求的前端项目都是必用缓存的
-
流程
- 浏览器每次发起请求,都会先在浏览器缓存中查找该请求的结果以及缓存标识
- 浏览器每次拿到返回的请求结果都会将该结果和缓存标识存 入浏览器缓存中
-
强缓存与协商缓存
强制缓存优先于协商缓存进行,若强制缓存(Expires和Cache-Control)生效则直接使用缓存,若不生效则进行协商缓存(Last-Modified / If-Modified-Since和Etag / If-None-Match),协商缓存由服务器决定是否使用缓存,若协商缓存失效,那么代表该请求的缓存失效,重新获取请求结果,再存入浏览器缓存中;生效则返回304,继续使用缓存,主要过程如下:
- 强缓存(200 from cache)时,浏览器如果判断本地缓存未过期,就直接使用,无需发起http请求
- 协商缓存(304)时,浏览器会向服务端发起http请求,然后服务端告诉浏览器文件未改变,让浏览器使用本地缓存
服务端如何校验option请求通过了
预检之后回应中有Origin字段,有允许的方法
跨域
-
同源策略
- 跨域出于浏览器的同源策略限制。同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略会阻止一个域的javascript脚本和另外一个域的内容进行交互。所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)
-
跨域类型
- 当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域
-
非同源限制
- 无法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB
- 无法接触非同源网页的 DOM
- 无法向非同源地址发送 AJAX 请求
-
跨域的解决方案
-
设置document.domain解决无法读取非同源网页的 Cookie问题
- 因为浏览器是通过document.domain属性来检查两个页面是否同源,因此只要通过设置相同的document.domain,两个页面就可以共享Cookie(此方案仅限主域相同,子域不同的跨域应用场景。
- 两个页面都设置
document.domain = 'test.com';
-
跨文档通信 API:window.postMessage()
- 调用postMessage方法实现父窗口http://test1.com向子窗口http://test2.com发消息(子窗口同样可以通过该方法发送消息给父窗口)
- 它可用于解决以下方面的问题:
- 页面和其打开的新窗口的数据传递
- 多窗口之间消息传递
- 页面与嵌套的iframe消息传递
- 上面三个场景的跨域数据传递
// 父窗口打开一个子窗口 var openWindow = window.open('http://test2.com', 'title'); // 父窗口向子窗口发消息(第一个参数代表发送的内容,第二个参数代表接收消息窗口的url) openWindow.postMessage('Nice to meet you!', 'http://test2.com'); //调用message事件,监听对方发送的消息 // 监听 message 消息 window.addEventListener('message', function (e) { console.log(e.source); // e.source 发送消息的窗口 console.log(e.origin); // e.origin 消息发向的网址 console.log(e.data); // e.data 发送的消息 },false);
-
JSONP
-
JSONP 是服务器与客户端跨源通信的常用方法。最大特点就是简单适用,兼容性好(兼容低版本IE),缺点是只支持get请求,不支持post请求。
-
核心思想:网页通过添加一个< script>元素,向服务器请求 JSON 数据,服务器收到请求后,将数据放在一个指定名字的回调函数的参数位置传回来。
-
为什么能实现跨域:jsonp跨域原理解析
-
原生实现
<script src="http://test.com/data.php?callback=dosomething"></script> // 向服务器test.com发出请求,该请求的查询字符串有一个callback参数,用来指定回调函数的名字 // 处理服务器返回回调函数的数据 <script type="text/javascript"> function dosomething(res){ // 处理获得的数据 console.log(res.data) } </script>
-
jQuery ajax:
$.ajax({ url: 'http://www.test.com:8080/login', type: 'get', dataType: 'jsonp', // 请求方式为jsonp jsonpCallback: "handleCallback", // 自定义回调函数名 data: {} });
-
Vue.js
this.$http.jsonp('http://www.domain2.com:8080/login', { params: {}, jsonp: 'handleCallback' }).then((res) => { console.log(res); })
-
-
CORS
-
CORS 是跨域资源分享(Cross-Origin Resource Sharing)的缩写。它是 W3C 标准,属于跨源 AJAX 请求的根本解决方法。
-
普通跨域请求:只需服务器端设置Access-Control-Allow-Origin
-
带cookie跨域请求:前后端都需要进行设置
-
**【前端设置】**根据xhr.withCredentials字段判断是否带有cookie
-
①原生ajax
var xhr = new XMLHttpRequest(); // IE8/9需用window.XDomainRequest兼容 // 前端设置是否带cookie xhr.withCredentials = true; xhr.open('post', 'http://www.domain2.com:8080/login', true); xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); xhr.send('user=admin'); xhr.onreadystatechange = function() { if (xhr.readyState == 4 && xhr.status == 200) { alert(xhr.responseText); } };
-
② jQuery ajax
$.ajax({ url: 'http://www.test.com:8080/login', type: 'get', data: {}, xhrFields: { withCredentials: true // 前端设置是否带cookie }, crossDomain: true, // 会让请求头中包含跨域的额外信息,但不会含cookie });
-
③vue-resource
Vue.http.options.credentials = true
-
④ axios
axios.defaults.withCredentials = true
-
-
【服务端设置】 服务器端对于CORS的支持,主要是通过设置Access-Control-Allow-Origin来进行的。如果浏览器检测到相应的设置,就可以允许Ajax进行跨域的访问。
-
① Java后台
/* * 导入包:import javax.servlet.http.HttpServletResponse; * 接口参数中定义:HttpServletResponse response */ // 允许跨域访问的域名:若有端口需写全(协议+域名+端口),若没有端口末尾不用加'/' response.setHeader("Access-Control-Allow-Origin", "http://www.domain1.com"); // 允许前端带认证cookie:启用此项后,上面的域名不能为'*',必须指定具体的域名,否则浏览器会提示 response.setHeader("Access-Control-Allow-Credentials", "true"); // 提示OPTIONS预检时,后端需要设置的两个常用自定义头 response.setHeader("Access-Control-Allow-Headers", "Content-Type,X-Requested-With");
-
② Nodejs后台
-
③ PHP后台
-
④ Apache
-
-
-
【5】webpack本地代理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-V03lhAlo-1646398367404)(/Users/wangke/Desktop/收集/图片/webpack代理实现CORS.png)]
-
在webpack.config.js中利用 WebpackDevServer 配置本地代理
-
如下简单配置案例,这样
http://localhost:8080/api/getUser.php
的请求就是后端的接口http://192.168.25.20:8088/getUser.php
devServer: { port: 8080, proxy: { "/api": { target: "http://192.168.25.20:8088" // 后端接口 } } }
-
-
Websocket
- Websocket 是 HTML5 的一个持久化的协议,它实现了浏览器与服务器的全双工通信,同时也是跨域的一种解决方案。WebSocket 和 HTTP 都是应用层协议,都基于 TCP 协议。但是 WebSocket 是一种双向通信协议,在建立连接之后,WebSocket 的 服务器与 客户端都能主动向对方发送或接收数据。同时,WebSocket 在建立连接时需要借助 HTTP 协议,连接建立好了之后 client 与 server 之间的双向通信就与 HTTP 无关了。
-
Nginx反向代理
-
-
首先得针对具体场景:
AJAX跨域:CORS JSONP WebSocket
cookie跨域:网页一级域名相同,二级域名不同,浏览器允许通过设置document.domain共享 Cookie。
iframe跨域:采用其他方法
其他解决方法:
- 片段识别符:用个#
- window.name:窗口中的网页可以读取,容量很大,只是要监听
- HTML5新特性:
- 跨文档通信API:调用postMessage()方法
- LocalStorage:也可以通过postMessage方法读取其他窗口的LocalStorage
浏览器多标签页通信
- WebSocket SharedWorker
- localStorage cookies
- 监听事件
Web安全
CSRF
-
特征
- 冒用用户身份,进行恶意操作
-
关键条件
- 采用cookie来进行用户校验
- 登录受信任网站A,并在本地生成Cookie
- 在不登出A的情况下,访问危险网站B
一般在(4)处恶意网站(B)的攻击手段如下(必须是指向A的地址,否则无法带上cookie):- 譬如在网站内的图片资源中潜入恶意的转账操作
<img src=http://www.bank.example/transfer?toBankId=hello&amount=1000000 width=’0‘ height=’0‘> - 构建恶意的隐藏表单,并通过脚本提交恶意请求
- 而且,从头到尾,攻击网站都没有获取到过 cookie,都是通过浏览器间接实现(利用Web的cookie隐式身份验证机制),所以HttpOnly并不会影响这个攻击
- 譬如在网站内的图片资源中潜入恶意的转账操作
-
防御
- 验证HTTP Referer字段(非常简单,但是鉴于客户端并不可信任,所以并不是很安全)
(防止CSRF,检查Referer字段简单直接,但是其完全依赖浏览器发送正确的Referer字段。
虽然http协议对此字段的内容有明确的规定,但并无法保证来访的浏览器的具体实现,
亦无法保证浏览器没有安全漏洞影响到此字段。并且也存在攻击者攻击某些浏览器,篡改其Referer字段的可能。) - 在请求地址中添加token并验证
(譬如post中,以参数的形式加入一个随机产生的token)
- 验证HTTP Referer字段(非常简单,但是鉴于客户端并不可信任,所以并不是很安全)
XSS(cross-site scripting)
- 特征
- 跨域脚本注入,攻击者通过某种方式将恶意代码注入到网页上,然后其他用户观看到被注入的页面内容后会受到特定攻击
- 从结果分类
- cookie劫持
- 会话伪造
- 其它恶意代码执行
- 从攻击者角度分类
- 预防
- 输入过滤,不信任用户的任何输入,过滤其中的“<”、“>”、“/”等可能导致脚本注入的特殊字符,或者过滤“script”、“javascript”等脚本关键字,或者对输入数据的长度进行限制等等,还得考虑攻击者使用十六进制编码来输入脚本的方式。
- 输出进行编码,和输入过滤类似,不过是从输出上着手,数据输出到页面时,经过HtmlEncoder等工具编码,这样就不会存在直接输出可执行的脚本了
- cookie设置http-only,这样用脚本就无法获取cookie了
(这样只有浏览器向Web服务器发起请求的时才会带上cookie字段,避免了XSS攻击利用JavaScript的document.cookie获取cookie) - Cookie防盗,尽可能地避免在Cookie中泄露隐私,如用户名、密码等;或者,为了防止重放攻击,可以将Cookie和IP进行绑定,这样也可以阻止攻击者冒充正常用户的身份。
- 注意,特别是后台,一定不能信任前端的输入,需要过滤与校验
SQL注入简介
前提是后台没有过滤前端的输入数据,否则根本无法生效
三次握手与四次握手
TCP三次握手、四次挥手
我们先回顾TCP三次握手、四次挥手的过程。
三次握手
Client:请求连接;
Server:同意并请求连接;
Client:同意。
四次挥手
Client:请求关闭;
Server:同意;
【Server:…(可能在继续发未发完的数据/也可能没有)】
Server:请求关闭;
Client:同意。
差别:
(1)三次握手:第二次握手时,服务器端同意客户端的连接请求的同时,进行服务器端的连接请求。
(2)四次握手:第二次握手时,服务器端仅同意客户端的关闭请求;在第三次握手时,才进行服务器端的关闭请求。
四次挥手可以三次吗?
四次挥手把同意对方请求跟自身请求分离开。是因为在客户端请求断开时(客户端发送端->服务器接收端),服务器可能还有数据未发完,所以需要分开操作:
-
先同意对方关闭连接,对方无法传输数据;(第二次挥手)
-
自己若还有数据未发送完,接着发送直至全部发送完毕;
-
请求自身关闭连接;(第三次挥手)
也就是说,三次握手、四次挥手差别就在第二次,有没有把同意对方请求跟自身请求拆分开。
如果客户端请求关闭连接时,服务器并没有数据需要发送,其实三次挥手应该也是可以的。但一般情况下,客户端猝不及防地请求断开连接,服务器还是有数据需要传输的,所以四次挥手更加地稳妥。
三次握手改成两次可以吗?
如客户端发出连接请求,但因连接请求报文丢失而未收到确认,于是客户端再重传一次连接请求。后来收到了确认,建立了连接。数据传输完毕后,就释放了连接,客户端共发出了两个连接请求报文段,其中第一个丢失,第二个到达了服务端,但是第一个丢失的报文段只是在某些网络结点长时间滞留了,延误到连接释放以后的某个时间才到达服务端,此时服务端误认为客户端又发出一次新的连接请求,于是就向客户端发出确认报文段,同意建立连接,不采用三次握手,只要服务端发出确认,就建立新的连接了,此时客户端忽略服务端发来的确认,也不发送数据,则服务端一致等待客户端发送数据,浪费资源。