HTTP无状态和connection:keep-alive的个人理解
http是一个无状态的面向连接的协议。
http无状态:无状态协议是指http协议本身对于事务处理没有记忆功能,服务器不知道浏览器的状态。通俗的即使你登录了,去访问同一个网站的不同网页,服务器都不会知道你是谁,如果需要记录登录用户的信息,用户操作,用户行为等数据需要使用cookie或session来存储。
keep-alive:从HTTP/11起,浏览器默认都开启了Keep-Alive,保持连接特性,客户端和服务器都能选择随时关闭连接,则请求头中为connection:close。简单地说,当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的TCP连接。但是Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间。
误解:无状态不代表HTTP不能保持TCP连接,更不能代表HTTP使用的是UDP协议(无连接)。即使http在无状态下,只要客户端和服务器的头部信息connection:keep-alive,则在有效期内他们使用同一条TCP连接。
自己的理解,在aspnet里:每次提交服务器的页面没有任何关系,每次记录在页面的信息下次提交是记不住的,(除了应用本身可能已经存储在全局对象中的所有信息外)在net里实际就是ViewState,ViewState是aspnet中保存页面信息的基本单位,应用时就是保存在控件隐藏域等中的数据协议的状态是指下一次传输可以“记住”这次传输信息的能力http是不会为了下一次连接而维护这次连接所传输的信息的无状态是指,当浏览器发送请求给服务器的时候,服务器响应,但是同一个浏览器再发送请求给服务器的时候,他会响应,但是他不知道你就是刚才那个浏览器,简单地说,就是服务器不会去记得你,所以是无状态协议。而DNS是有状态协议 。HTTP是一个属于应用层的面向对象的协议,HTTP协议一共有五大特点,1、支持客户/服务器模式;2、简单快速;3、灵活;4、无连接;5、无状态;“无状态”是HTTP协议的主要特点之一,以下为“无状态”的解释。 无状态:是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。既然HTTP协议的目的在于支持超文本的传输,更加广义一些就是支持资源的传输,那么在客户端浏览器向HTTP服务器发送请求,继而HTTP服务器将相应的资源发回给客户端这样一个过程中,无论对于客户端还是服务器,都没有必要记录这个过程,因为每一次请求和响应都是相对独立的,就好像你在自动售货机前投下硬币购买商品一样,谁都不会也不需要记住这样一个交易过程。一般而言,一个URL对应着唯一的超文本,而HTTP服务器也绝对公平公正,不管你是Michael,还是Jordon,它都会根据接收到的URL请求返回相同的超文本。正是因为这样的唯一性,使得记录用户的行为状态变得毫无意义,所以,HTTP协议被设计为无状态的连接协议符合它本身的需求。然而,随着时间的推移,人们发现静态的HTML着实无聊而乏味,增加动态生成的内容才会令Web应用程序变得更加有用。于是乎,HTML的语法在不断膨胀,其中最重要的是增加了表单(Form);客户端也增加了诸如脚本处理、DOM处理等功能;对于服务器,则相应的出现了CGI(Common Gateway Interface)以处理包含表单提交在内的动态请求。在这种客户端与服务器进行动态交互的Web应用程序出现之后,HTTP无状态的特性严重阻碍了这些应用程序的实现,毕竟交互是需要承前启后的,简单的购物车程序也要知道用户到底在之前选择了什么商品。于是,两种用于保持HTTP连接状态的技术就应运而生了,一个是Cookie,而另一个则是Session。Cookie是通过客户端保持状态的解决方案。从定义上来说,Cookie就是由服务器发给客户端的特殊信息,而这些信息以文本文件的方式存放在客户端,然后客户端每次向服务器发送请求的时候都会带上这些特殊的信息。让我们说得更具体一些:当用户使用浏览器访问一个支持Cookie的网站的时候,用户会提供包括用户名在内的个人信息并且提交至服务器;接着,服务器在向客户端回传相应的超文本的同时也会发回这些个人信息,当然这些信息并不是存放在HTTP响应体(Response Body)中的,而是存放于HTTP响应头(Response Header);当客户端浏览器接收到来自服务器的响应之后,浏览器会将这些信息存放在一个统一的位置,对于Windows操作系统而言,我们可以从:[系统盘]:\Documents and Settings\[用户名]\Cookies目录中找到存储的Cookie;自此,客户端再向服务器发送请求的时候,都会把相应的Cookie再次发回至服务器。而这次,Cookie信息则存放在HTTP请求头(Request Header)了。有了Cookie这样的技术实现,服务器在接收到来自客户端浏览器的请求之后,就能够通过分析存放于请求头的Cookie得到客户端特有的信息,从而动态生成与该客户端相对应的内容。通常,我们可以从很多网站的登录界面中看到“请记住我”这样的选项,如果你勾选了它之后再登录,那么在下一次访问该网站的时候就不需要进行重复而繁琐的登录动作了,而这个功能就是通过Cookie实现的。与Cookie相对的一个解决方案是Session,它是通过服务器来保持状态的。由于Session这个词汇包含的语义很多,因此需要在这里明确一下Session的含义。首先,我们通常都会把Session翻译成会话,因此我们可以把客户端浏览器与服务器之间一系列交互的动作称为一个Session。从这个语义出发,我们会提到Session持续的时间,会提到在Session过程中进行了什么操作等等;其次,Session指的是服务器端为客户端所开辟的存储空间,在其中保存的信息就是用于保持状态。从这个语义出发,我们则会提到往Session中存放什么内容,如何根据键值从Session中获取匹配的内容等。要使用Session,第一步当然是创建Session了。那么Session在何时创建呢?当然还是在服务器端程序运行的过程中创建的,不同语言实现的应用程序有不同创建Session的方法,而在Java中是通过调用HttpServletRequest的getSession方法(使用true作为参数)创建的。在创建了Session的同时,服务器会为该Session生成唯一的Session id,而这个Session id在随后的请求中会被用来重新获得已经创建的Session;在Session被创建之后,就可以调用Session相关的方法往Session中增加内容了,而这些内容只会保存在服务器中,发到客户端的只有Session id;当客户端再次发送请求的时候,会将这个Session id带上,服务器接受到请求之后就会依据Session id找到相应的Session,从而再次使用之。正式这样一个过程,用户的状态也就得以保持了。有关Session的内容还比较多,在以后的Post中,我还将继续讲述。
客户端服务器意图提供一个可缩放 (scaleable)的架构,借此网上的计算机或者处理过程是一个客户端或者服务器。服务器软件一般,但不是总是,运行在强大的专用商业计算机上。另一方面,客户端一般运行在普通个人电脑或者工作站上。
服务端的特征:
被动的角色(从)。 等待来自客户端的要求。 处理要求并传回结果。
客户端的特征:
主动的角色(主)。 发送要求。 等待直到收到回应。 服务器可是有状态或者无状态的。无状态的服务器不会保留任何两个请求之间的信息,有状态服务器会记住请求之间的信息。这些信息的作用域可以是全局的或者某个事务 (session)的。静态 HTML 页面服务器是一个无状态服务器的例子,Apache Tomcat 是一个有状态服务器。
服务端与客户端的交互经常使用循序图描述,循序图是 UML 中的一个标准。
另一种已知的网络架构类型是点对点架构(peer-to-peer architecture),因为每一个即点或程序的实体都是客户端与服务器的角色,并且具有对等的责任。目前这两种架构都被广泛使用。
HTTP是无状态的
也就是说,浏览器和服务器每进行一次HTTP操作,就建立一次连接,但任务结束就中断连接。如果客户端浏览器访问的某个HTML或其他类型的 Web页中包含有其他的Web资源,如JavaScript文件、图像文件、CSS文件等;当浏览器每遇到这样一个Web资源,就会建立一个HTTP会话
HTTP11和HTTP10相比较而言,最大的区别就是增加了持久连接支持(貌似最新的 http10 可以显示的指定 keep-alive),但还是无状态的,或者说是不可以信任的。
如果浏览器或者服务器在其头信息加入了这行代码
Connection:keep-alive
TCP连接在发送后将仍然保持打开状态,于是,浏览器可以继续通过相同的连接发送请求。保持连接节省了为每个请求建立新连接所需的时间,还节约了带宽。
实现长连接要客户端和服务端都支持长连接。
所谓长连接指建立SOCKET连接后不管是否使用都保持连接,但安全性较差,
所谓短连接指建立SOCKET连接后发送后接收完数据后马上断开连接,一般银行都使用短连接
短连接:比如
http
的,只是连接、请求、关闭,过程时间较短
,
服务器若是一段时间内没有收到请求即可关
闭连接。
长连接:有些服务需要长时间连接到服务器,比如
CMPP
,一般需要自己做在线维持。
最近在看
“
服务器推送技术
”
,在
B/S
结构中,通过某种
magic
使得客户端不需要通过轮询即可以得到服务
端的最新信息(比如股票价格)
,这样可
以节省大量的带宽。
传统的轮询技术对服务器的压力很大,
并且造成带宽的极大浪费。如果改用
ajax
轮询,可以降低带宽的负荷
(因为服务器返回的不是完整页面)
,
但是对服务器
的压力并不会有明显的减少。
而推技术(
push
)可以改善这种情况。但因为
HTTP
连接
的特性(短暂,必须由客户端发起)
,使得推技术的实现比较困难,常见的做法是通过延长
http
连接的寿
命
,
来实现
push
。
接下来自然该讨论如何延长
http
连接的寿命
,
最简单的自然是死循环法
:
servlet
代
码
片
段
public
void
doGet(Request
req,
Response
res)
{
PrintWriter
out
=
resgetWriter();
……
正
常
输
出
页
面
……
outflush();
while
(true)
{
outprint("
输
出
更
新
的
内
容
");
outflush();
Threadsleep(3000);
}
}
如果使用观察者模式则可以进一
步提高性能。
但是这种做法的缺点在于客户端请求了这个
servlet
后,
web
服务器会开启一个线程执行
servlet
的代码,而
servlet
由迟迟不肯结束,造成
该线程也无法被释放。于是乎,一个客户端一个线程,
当客户端数量增加时,服务器依然会承受很大的负担。
要从根本上改变这个现象比较复杂,目前的趋
势是从
web
服务器内部入手,用
nio
(
JDK
14
提出的
javanio
包)改写
request/response
的实现,再利
用线程池增强服务器的资源利用率,从而解决这个问题,目前支持这一非
J2EE
官方技术的服务器有
Glassfish
和
Jetty
(后者只是听说,没有用过)
无状态是针对于“状态”来说的。
一个WEB应用协议中的“状态”指的是,为两个相互关联的用户交互操作保留某种公共信息,例如用户登录信息,工作流等。
这些信息具有不同作用域,如page,request,session,application等。通常由服务器负责保存这些信息。
“无状态”
的概念逐渐流行,得益于分布式系统的发展。首先,无状态请求易于实现负载均衡。在分布式web系统下,有多个可用服务器,每个服务器都可以处理客户端请求。
传统的有状态请求,因为状态信息只保存在第一次发起请求的那台服务器上,之后的请求都只能由这台服务器来处理,服务器无法自由调度请求。无状态请求则完全没有这个限制。其次,无状态请求有较强的容错性和可伸缩性。如果一台服务器宕机,无状态请求可以透明地交由另一台可用服务器来处理,而有状态的请求则会因为存储请求状态信息的服务器宕机而承担状态丢失的风险。
需要注意的是,“状态"指请求的状态,而不是资源的状态。Restful风格的无状态约束要求服务器不保存请求状态,如果确实需要维持用户状态,也应由客户端负责。传递user
credentials 是Restful的,而传递sessionID是unRestful的,因为session信息保存在服务器端。
IPv6无状态地址生成是使用EUI-64算法来产生唯一的IPv6地址,该方法使用MAC地址的后64位来创建IPv6地址。以下是IPv6无状态地址生成的步骤:1 获取MAC地址,它是由48位二进制数表示的全球唯一的地址。2 将MAC地址的第7位(从右数起)的2进制位改为1,以在使用EUI-64算法时生成IPv6地址。3 将MAC地址的前3个字节(即前6个十六进制数)分组并拼接为“fffe”。4 在步骤3上添加分隔符号“:”,将MAC地址的后3个字节拼接在其后面。5 将IPv6前缀加入MAC地址,并用“:”分隔符分隔。6 如果IPv6网络使用了IPv4映射到IPv6,还需要在IPv6地址前添加“::ffff:”前缀。例如,假设MAC地址为08:00:27:56:32:45和IPv6前缀为2001:db8:1234:5678::/64,按照上述步骤生成的IPv6地址为:2001:db8:1234:5678:0a00:27ff:fe56:3245注意,该方法只适用于无状态地址生成模式。在动态主机配置协议(DHCPv6)模式下,IPv6地址通常由DHCPv6服务器分配。
由于http 协议是一种无状态的协议,服务器端并不知道客户端的那一头是谁在请求服务器。而且服务器上的资源不一定是对所有人开放,所以需要进行用户对登录鉴权。目前,我们在开发中主要使用过4 种鉴权方式。
这种授权方式是浏览器遵守http协议实现的基本授权方式。
优点基本上所有流行的网页浏览器都支持基本认证。基本认证很少在可公开访问的互联网网站上使用,有时候会在小的私有系统中使用(如路由器网页管理接口)。后来的机制HTTP摘要认证是为替代基本认证而开发的,允许密钥以相对安全的方式在不安全的通道上传输。 程序员和系统管理员有时会在可信网络环境中使用基本认证,使用Telnet或其他明文网络协议工具手动地测试Web服务器。这是一个麻烦的过程,但是网络上传输的内容是人可读的,以便进行诊断。
缺点虽然基本认证非常容易实现,但该方案创建在以下的假设的基础上,即:客户端和服务器主机之间的连接是安全可信的。特别是,如果没有使用SSL/TLS这样的传输层安全的协议,那么以明文传输的密钥和口令很容易被拦截。该方案也同样没有对服务器返回的信息提供保护。 现存的浏览器保存认证信息直到标签页或浏览器被关闭,或者用户清除历史记录。HTTP没有为服务器提供一种方法指示客户端丢弃这些被缓存的密钥。这意味着服务器端在用户不关闭浏览器的情况下,并没有一种有效的方法来让用户注销。
优缺点
session-cookie的缺点
(1)认证方式局限于在浏览器中使用, cookie 是浏览器端的机制,如果在app端就无法使用 cookie 。
(2)为了满足全局一致性,我们最好把 session 存储在 redis 中做持久化,而在分布式环境下,我们可能需要在每个服务器上都备份,占用了大量的存储空间。
(3)在不是 Https 协议下使用 cookie ,容易受到 CSRF 跨站点请求伪造攻击。
token 是一个令牌,当浏览器第一次访问服务端时会签发一张令牌,之后浏览器每次携带这张令牌访问服务端就会认证该令牌是否有效,只要服务端可以解密该令牌,就说明请求是合法的。一般 token 由用户信息、时间戳和由 hash 算法加密的签名构成。
优点 :
(1) token 认证不局限于 cookie ,这样就使得这种认证方式可以支持多种客户端,而不仅是浏览器。且不受同源策略的影响。
(2)不使用 cookie 就可以规避CSRF攻击。
(3) token 不需要存储, token 中已包含了用户信息,服务器端变成无状态,服务器端只需要根据定义的规则校验这个 token 是否合法就行。这也使得 token 的可扩展性更强。
缺点 :
(1)加密解密消耗使得 token 认证比 session-cookie 更消耗性能。
(2) token 比 sessionId 大,更占带宽。
由于app没有浏览器无法存储cookie,故出现了OAuth,且允许用户授权第三方网站访问他们存储在另外的服务提供者上的信息,与以往的授权方式不同之处是OAuth的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此OAuth是安全的。
众所周知,http的连接是无状态的。
HTTP无状态协议是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。
通俗一点讲就是你每次请求服务器的时候,它并不知道你是谁,但实际上现在的网站并不是这样的,因为它们使用了cookie和session来辅助服务器记住你是谁,简单来讲这两者就是你进入这个网站的钥匙。关于cookie和session的具体内容和差别,可以去找度娘聊聊。
可能有的同学会有疑问,我在做网站开发的时候并没有设置cookie啊,那是怎么识别用户的呢?
其实在你首次登陆某个网站的,没有任何cookie的时候(首次登陆或者清除),服务器会给你返回一个自生成的id(tomcat默认的叫JSESSIONID,百度的叫BAIDUID,简书的叫_session_id,当然每个都可能不一样,这个是可以自定义的)cookie值写入你的浏览器。那这个sessionid(以下都会这么叫)就是你进入网站的钥匙。当你登陆的时候,请求会携带这个cookie值传入后台。
(向后台传递的数据)
一般登陆后台的处理就是如果用户登陆成功,那么就将用户id或者。。。保存至session中,那这样就生成了一条识别链。
(简易的识别链)
大概的解释一下:当程序需要为某个客户端的请求创建一个session时,服务器首先检查这个客户端的请求里是否已包含了一个session标识称为sessionid,如果已包含则说明以前已经为此客户端创建过session,服务器就按照sessionid把这个session检索出来使用(检索不到,会新建一个),如果客户端请求不包含sessionid,则为此客户端创建一个session并且生成一个与此session相关联的sessionid,sessionid的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串,这个sessionid将被在本次响应中返回给客户端保存。之后的每次访问都会携带上这个sessionid,然后查找对应的session和session中的值,服务器进行登陆判断和权限判断。
关闭浏览器、长时间没有请求服务器、注销登陆,这个时候服务器会把该sessionid从内存中清除掉,这个时候如果我们再去请求服务器,sessionid已经不存在了,所以服务器并没有在内存中找到对应的 sessionid,所以会再产生一个新的sessionid,这个时候一般我们又要再登录一次。
细心的同学会发现,那么是不是意味着,如果我拿到了你这个sessionid我就可以冒充你来访问这个网站了?没有错,如果网站没有很好的防护,确实可以这么做。具体怎么实现我这就不太方便说了,感兴趣也可以度娘cookie窃取欺骗和攻击。
所以请各位同学保护好自己的cookie,不要轻易被偷窃走哦。
0条评论