作者:赛艇队长

cnblogs.com/bellkosmos/p/5237146.html

引子

最近在好好了解http,发现对介绍http的第一句话【http协议是无状态的,无连接的】就无法理解了:无状态的【状态】到底指的是什么?!

找了很多资料不仅没有发现有一针见血正面回答这个问题的,而且有些解释还充斥了各种错误,看着看着就觉得心里憋着一股浊气吐不出来

于是在看了很多资料之后,我一口吐出浊气,大声正面提出这个问题:http协议无状态中的【状态】到底指的是什么?!

然后开始不断探索解决这个问题。。。

最终很高兴的是我找到了让人满意的答案,先卖个关子,各位如果着急可以直接拉到最下查看

正文

http协议无状态中的【状态】到底指的是什么?!

1.先来看这句话的另外两个概念:(标准的http协议是无状态的,无连接的) 标准的http协议指的是不包括cookies, session,application的http协议,他们都不属于标准协议,虽然各种网络应用提供商,实现语言、web容器等,都默认支持它

2.无连接指的是什么

  • 每一个访问都是无连接,服务器挨个处理访问队列里的访问,处理完一个就关闭连接,这事儿就完了,然后处理下一个新的

  • 无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接

对于【无状态】,我看到很多隔着一层磨砂玻璃一样的模糊说法(官方或者教程里的说法),看着非常难受(但其实算是对的)(后来我发现我为什么觉得它看着难受了,因为他们引入了很多新的,而且明显是一个可能用在很多地方的广义名词,这些词最大的作用就是,混淆概念,下面我标注了)

  • 协议对于事务处理没有记忆能力【事物处理】【记忆能力】

  • 对同一个url请求没有上下文关系【上下文关系】

  • 每次的请求都是独立的,它的执行情况和结果与前面的请求和之后的请求是无直接关系的,它不会受前面的请求应答情况直接影响,也不会直接影响后面的请求应答情况【无直接联系】【受直接影响】

  • 服务器中没有保存客户端的状态,客户端必须每次带上自己的状态去请求服务器【状态】

我必须得到确切而具体的解释!

这几点给了我下一步思考的方向:

1.【服务器中没有保存客户端的状态,客户端必须每次带上自己的状态去请求服务器 】这里的客户端的状态是不是确切地指服务器没有保存客户的信息呢?但显然不是啊

2.【HTTP无状态的特性严重阻碍了这些应用程序的实现,毕竟交互是需要承前启后的,简单的购物车程序也要知道用户到底在之前选择了什么商品】我对此质疑为什么无状态就不能实现购物车呢?服务器就不能存储东西了么?

3.【 每次的请求都是独立的,<它的执行情况和结果>与<前面的请求>和<之后的请求>是无直接关系的】我觉得这个说法比较靠谱,但是所谓的不同请求间的没有关系,是指的请求内容没有关系,还是只是指请求本身没有关系?

  • 请求内容没有关系只可能是服务器上不存有用户数据才可能啊,但是显然是存有的啊

  • 请求本身没有关系,这又有什么意义呢,每一次的请求有什么价值?

根据这个方向我做了一个模拟访问实验:假如没有cookie没有session,只有http的时候,那当一个注册用户访问这个购物网站的时候,会发生这些事情:

1.前提情况:

  • 服务器肯定为每个注册用户建立了数据表,记录用户的数据

  • http是无连接的

2.第一步需要登录

  • 用户通过http把用户的用户名和密码发送给服务器,服务器把他们跟自己存有的用户资料对比,如果一致,则返回信息登录成功

3.然后用户点击某一商品页

  • 这个动作相当于输入一个商品页的网址

  • 假如商品页比较机密不对外公开,需要是用户才能访问

  • 而虽然http能传送用户名和密码,而且刚才也输入了,还验证成功了,但是因为服务器既不会记得你登录的状态,你的客户端也不会存储你刚才输入的用户名和密码

  • 所以因为这一次访问因为无法确定你的身份,只能访问失败

    • 这时候如果要解决这个问题,而且没有cookie没有session,那就只能你在访问网址的同时继续带上你的用户名和密码(继续输入咯)其实就像我现在的APP一样

4.假设上一步的问题解决了,就是每次访问的时候都会手动输入用户名和密码,然后现在的情况是:你已经选了几件商品在你的购物车中,你想再添加一件商品,于是你点击某个商品旁边的加号

  • 这个动作也相当于输入一个网址,网址的内容是发送一个请求,往你的购物车中加入这个商品

  • 系统首先用你传来的用户名和密码验证你的身份,然后访问你的数据库,在其中的购物车属性下加一条数据,就是这个商品的数据

  • 操作结束后,返回操作成功,并结束访问

5.OK,实验结束,看似没有cookie没有session也能凑合解决问题,其实两个操作都有很大的问题

  • 你每访问一次需要权限的内容都需要在客户端输入用户名和密码,这一项的繁琐就不必赘述了

  • 你的每一次操作都要与系统底层的数据库进行交互

    • 多次少量的访问存在非常大的性能浪费。非常容易就能想到肯定是一次大量的操作更加有效率,于是就想到了缓存区

  • 你的非重要琐碎数据也被写进数据库中,跟你的主要数据放在一起

    • 一次次添加和删除购物车其实只是跟你这次浏览,或者叫这次会话有关,是临时的数据,跟用户的主要信息无关,它们没什么价值,纯粹的冗余数据(不排除现在有的公司觉得这种数据也有非常大的价值可以让它们巧妙的利用),用什么存放这些临时的数据,我们也很容易想到缓存区

搜索Java知音公众号,回复“后端面试”,送你一份Java面试题宝典

经过这个模拟访问实验,结合前面的思考方向,我们知道了三点:

  • 服务器上肯定存有用户的数据,你提交的增删改查它也能够处理,所以这句话中【服务器中没有保存客户端的状态】的状态并不是指用户的数据,我们的猜测不对

  • 我们的质疑对了,无状态能实现购物车,可以通过服务器上存有的用户数据来实现

  • 但是,使用上面这种方式实现购物车,存在三个比较大的问题。由此,我们不禁会想,这三个问题的解决是不是跟我们不确切了解的【状态】一词有关?于是,接下来我们来通过解决这三个问题来把【状态】的意义探寻下去

由上所述,我们可以在http的基础上增加一些机制来解决上面出现的三个问题

1.在用户端增加一个记录本是非常有必要的,正好官方加入的cookie机制跟这个一样,它的用处也确实是上面讨论的那样,一般就是用来标识访问者的身份

2.在服务器增加一个缓存区能同时解决后两个问题

  • 有了这个缓存区作为一个数据缓冲,就不用一次次地访问数据库,浪费大量计算机资源,而是在最后统一归入数据库

  • 有了这个缓存区,你就不用把临时的数据放到数据库中了,只需要在你们交流告一段落之后,再把数据整理,把有用的数据归入数据库

3.这里就自然引申出了一个重要的概念:会话,它作为一个缓冲存储区被从数据库中分离出来,理由并不生硬,它有其独特的重要且不可替代的作用。这个东西恰好跟官方加入的session机制一样

3.1.另外说一个非常具有迷惑性的容易让人对session的主要作用产生偏离的理解:认为session存在的价值就是给访问者分配一个sessionID代替用户名和密码,

3.2.为什么非常具有迷惑性,因为session确实做了这件事,而且也起到了很大的作用,所以它是对的,但是只对一半,而且没有涉及问题的本质,这种情况是最危险的(看似很有说服力,把你说服了,所以你很难有动力继续找下去,但是真实情况跟它有偏差,但是偏差不大,所以又很难把你说服回来,只有隐隐的不对劲,这个时候你离真实最近,也离真实最远)

3.3.那就顺便说说它为什么是对的,也就是用session做的另一件有用的事:

  • 给每个session一个ID,一方面用来方便自己查询,另一方面把这个ID给用户,用户下一次访问的时候就可以不用用户名和密码,而是直接使用这个ID来表明自己的身份

  • 首先,这个ID安全吗?这个ID比直接传用户名和密码安全吗?

    • 不严格加密的sessionID和用户名和密码一样,都不太安全

    • 但是相比较来说,sessionID要安全一些

    • 而使用https是完全安全的

  1. 你很容易会想到,本来用户名和密码的组合还特地设置地比较复杂,你这换一组数字就代替了,是不是太不安全了?

  2. 我们知道http协议本身是完全不加密的,如果使用用户名和密码,第一次访问是放在http头中,后边自动保存了密码就会放在cookie中,这些都完全没有加密,它的安全性基本为0,就是裸奔了,只要被窃取,那就丢失了

  3. 所以,就这个意义来讲,sessionID的安全性跟使用用户名和密码没什么区别

  4. 但是其实,虽然http本身不能加密,但是有些软件什么的,能在应用层面手动给你加密,比如QQ就会使用户名密码加临时验证码联合哈希,sessionID加一个时间戳简单加密也是非常常用的方法

  5. 而且因为sessionID本身有有效期,即使丢了,也可能很快失效,造成的损失可能没那么大,而用户名跟密码丢了,那就大了

  6. 所以总结就是:

  • 然后,使用sessionID有哪些好处

    1. 方便直接根据ID查询用户对应的session

    2. 加密的时候计算量小

    3. 安全性不会降低,甚至还更高一些

    OK,通过独立地解决纯http机制会产生的问题,我们探讨了cookie和session机制的本质。而且想到:【使用http协议,服务器中不会保存客户端的状态】所产生的问题通过增加cookie和session机制解决了,是不是就意味着这个【状态】跟cookie和session的关系非常紧密?

    所以这个无状态指的是【没有对 本次会话 设置一个缓存区,记录这次会话的状态,缓存区包括服务器端和用户端】但好像还是没有点破关键(主要是觉得跟前面那些官方对状态的说法不太吻合,甚至没有对应关系)

    搜索Java知音公众号,回复“后端面试”,送你一份Java面试题宝典

    忽然我想到一个问题:一个有状态的http是什么样的?

    1.很难直接想象有状态的http是什么样,因为http这种机制是天然无状态的

    2.那就类比一下吧,另一个天然有状态的机制叫TCP

    • 如果有状态的意思是它的每次请求是有联系的,那么有状态的TCP的样子是:假如一份数据分了三份TCP包发送,那这个包上面会标明这是第几个包,会标明这个包跟那几个包是有联系的,有什么联系

    3.但好像这个有状态的TCP跟我们想要的有状态的HTTP没有关系,因为即使每次http请求之间互相有联系,它也不能解决上面提到的http无状态的问题

    4.诶,等等,好像能类比:

    4.1.假如每个http连接都有一个签名,于是第一次登陆成功之后,服务器就知道了这个签名是允许登陆的,于是之后所有同样签名的http连接都能登陆,这里利用了同一个用户发出的http连接之间的同主人关系,这里解决了一个保持登录状态的问题

    4.2.同样,来尝试利用这个【每次http请求之间互相有联系】来解决上面碰到的那个问题【每一次操作都要与系统底层的数据库进行交互】,但想了半天确实无法进行下去。往期:一百期面试题汇总

    4.3.不过我灵机一动,从另一个角度来想,好像解决了这个问题:

    1. 只有【每次http请求之间互相有联系】这个条件,无法解决【每一次操作都要与系统底层的数据库进行交互】

    2. 因为很明显,要解决【每一次操作都要与系统底层的数据库进行交互】就必须在服务器端开辟一块缓存区

    3. 不过如果你思考一下如何实现【每次http请求之间互相有联系】,你就会发现,它也需要在服务器端开辟一块缓存区

    4. 所以【在服务器端开辟一块缓存区】才是真正的条件,也就是说,它确实等价于【有状态】

    5. 而且我也找到了这个【在服务器端开辟一块缓存区】的条件跟前面那些官方对状态的说法对应的点,那就是:

    • 通过在服务器端开辟一块缓存区,存储、记忆、共享一些临时数据,你就可以:

    • 协议对于事务处理有记忆能力【事物处理】【记忆能力】

    • 对同一个url请求有上下文关系【上下文关系】

    • 每次的请求都是不独立的,它的执行情况和结果与前面的请求和之后的请求是直接关系的【不独立】【直接关系】

    • 服务器中保存客户端的状态【状态】

    1. 所以,这个状态,加上前面说的客户端也有cookie,就是指,客户端和服务器在临时会话中产生的数据!而前面也说道了,使用缓存区保存临时会话中的数据是多么重要

    • 所以状态不仅包括不同URL访问之间的关系,还有对其他URL访问的数据记录,还有一些其他的东西,所以更确切地说,状态应该是【实现了这些东西所凭借的后面的缓存空间】中的客户的临时数据

    • cookie和session应该是完全实现了有状态这个功能

    一种常见的对状态的误解:

    • 有人在解释HTTP的无状态时,把它跟有连接对立,说是两种方式,也就是如果想不无状态,就必须有连接,但其实不然

    • 有连接和无连接以及之后的Keep-Alive都是指TCP连接

    • 有状态和无状态可以指TCP也可以指HTTP

    • TCP一直有状态,HTTP一直无状态,但是应用为了有状态,就给HTTP加了cookie和session机制,让使用http的应用也能有状态,但http还是无状态

    • 开始TCP是有连接,后来TCP无连接,再后来也就是现在TCP是Keep-Alive,有点像有连接

    琐碎时间想看一些技术文章,可以去公众号菜单栏翻一翻我分类好的内容,应该对部分童鞋有帮助。同时看的过程中发现问题欢迎留言指出,不胜感谢~。另外,有想多了解哪些方面内容的可以留言(什么时候,哪篇文章下留言都行),附菜单栏截图(PS:很多人不知道公众号菜单栏是什么)

    END

    我知道你 “在看”
    

难住了N个面试者,http协议无状态中的 状态 到底指的是什么?!相关推荐

  1. 面试官:简单说说Java8中的HashMap到底有啥变化?

    作者:废物大师兄 https://cnblogs.com/cjsblog/p/8207211.html JDK1.8中的HashMap实现跟JDK1.7中的实现有很大差别.下面分析JDK1.8中的实现 ...

  2. 【Java面试题】6年开发去A里面试P6竟被Mysql难住了,说一下你对行锁、临键锁、间隙锁的理解

    一个工作了6年的程序员,最近去阿里面试p6这个岗位. 面试之前信心满满的和我说,这次一定要拿下 35k月薪的offer. 然后,在第一面的时候,被Mysql里面的一个问题难住了. 大家好,我是Mic, ...

  3. 腾讯二面,我被 “赛马” 问题难住了

    很难一次答对的经典面试题,处处是坑 大家好,我是鱼皮. 今天分享一道我曾经被难住了的面试题,也是一道大厂面试时经常会被问到的面试题,赛马问题. 题目其实不难,但是第一次被问到时,稍有不慎,就会答错.所 ...

  4. vb初学者编程代码大全_学习VB编程第14天,一个简单的排序代码把我难住了

    今天学习了刘金玉老师VB编程教程的第21期,学习的主要内容是冒泡排序算法. 一.算法的主要种类 1.算法的种类有冒泡排序法.选址排序法.折半查找法.快速排序法.穷举法等. 2.补充知识:variant ...

  5. 小学三年级另类语文题难住大学副教授(图)

    看到这些题蔡先生也犯难 记者 阚旋 摄 小学三年级的语文卷,不仅有你想不到的,也还有你做不到的. 昨日,一套小学生三年级语文作业题,难住了长春某大学副教授蔡先生. 两天答完159个小题 "这 ...

  6. 在一些测试的时候,我总是被考“思维定势”的题目给难住

    在一些测试的时候,我总是被考"思维定势"的题目给难住!郁闷!!!! 例如:两根不均匀的香,各能燃烧1个小时,问现在比赛时间是45分钟,要如何确定时间?总共能确定几种时间? 以下,是 ...

  7. 啃下这三块最难啃的硬骨头,你将在嵌入式C语言中大放异彩

    啃下这三块最难啃的硬骨头,你将在嵌入式C语言中大放异彩 C语言在嵌入式学习中是必备的知识,审核大部分操作都要围绕C语言进行,而其中有三块"难啃的硬骨头"几乎是公认级别的. ///插 ...

  8. java面试大全(7w字,更新中)

    1.杂题 1.maven依赖冲突的解决方法 依赖冲突的原因 举个例子,A依赖于B与C,B依赖于D的1.0版本,C依赖于D的2.0版本,这就导致加载的时候到底会引入那个版本的jar包的问题 解决方法: ...

  9. 面试:TCP协议经典十五连问!

    以下文章来源方志朋的博客,回复"666"获面试宝典 前言 TCP协议是大厂面试必问的知识点.整理了15道非常经典的TCP面试题,希望大家都找到理想的offer呀 1.  讲下TCP ...

最新文章

  1. 团队-石头,剪刀,布-设计文档
  2. GitHub发布开源项目指南,以帮助更多开发者参与开源
  3. Mac的最小化和隐藏的区别
  4. 面向机器学习的特征工程 三、文本数据: 展开、过滤和分块
  5. 奇文:金庸小说中的第一高手是谁?
  6. 解决虚拟机在能ping通网关情况下出现From 192.168.1.10: icmp_seq=1 Redirect Network(New nexthop: 192.168.1.1)问题
  7. HDU 5936 2016CCPC杭州 D: Difference(折半枚举)
  8. pycharm appiunm 公众号测试_知道答案公众号_知到APP笔尖上的艺术——书法基础与赏析单元测试答案_知道答...
  9. HDU2147 kiki's game
  10. lisp型材库_基于Auto LISP 创建V 带轮标准件库
  11. 使用 OpenSSL 生成 HTTPS 证书
  12. android 悬浮窗截屏,GitHub - tyhjh/ScreenShot: Android截屏的封装
  13. MySQL JSON_EXTRACT()、JSON_UNQUOTE() 函数获取JSON串的值
  14. tempo jsnode扩展 3d图形支持。
  15. paypal沙盒用户_如何使用PayPal实施用户登录
  16. Doom3 引擎渲染管线分析
  17. 赛季更新服务器维修,12月30日第一赛季结束 夺神之权服务器停机维护公告
  18. iphone装android软件,黑科技降临,红手指教你苹果手机如何安装安卓APP
  19. 数据传输完整性_基于IBIS模型的FPGA信号完整性仿真验证方法
  20. 李炎恢ECMAScript6 / ES6+(一)

热门文章

  1. 特斯拉中国向招商银行贷款50亿元 工厂本月开始生产
  2. 余承东谈华为6G:正在研发,还需要10年时间
  3. 维信诺全柔AMOLED产线启用 对“加入华为供应链”一事避而不谈
  4. 8月29日见!卢伟冰:Redmi首款互联网电视将采用70英寸巨屏
  5. 第一款青少年搜索引擎“花漾搜索“APP正式上线
  6. 谷歌看下!罗永浩谈谷歌砍掉平板线 :主要是因为软件太烂
  7. 在线打假!“鲁迅说过的话”检索系统上线 网友太热情系统一度崩溃
  8. iQOO高层专访:打造性能旗舰 用户满意度为先
  9. 挤爆了!故宫首次晚间开放:预约票平台一度502
  10. 已从事软件测试一年,感觉依然很菜,只会基础的功能测试,想进一步学习,有没有好的建议呢?