第一章 web服务器的工作原理及过程
1.1基本原理
一、tcp三次握手
第一次握手:发送请求连接包给服务器。客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手:服务器收到请求连接后,返回一个可以连接的应答包。服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到应答包后再向服务器端发送收到应答包的确认包。客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
二、socket
程序通过socket进行通信。作为进程通信机制,用于描述IP地址,端口,是一个通信链的句柄。sochet实际上是对tcp/ip协议的封装,socket本身不是协议,而是一个调用接口(API)
通过Socket,我们才能使用TCP/IP协议。TCP/IP也要提供可供程序员做网络开发所用的接口,这就是Socket编程接口。
socket函数接口:,比如create、listen、connect、accept、send、read和write等等。
套接字之间的连接过程分为三个步骤:服务器监听,客户端请求,连接确认。
1、服务器监听:服务器生成一个监听socket,实时监听来访socket。服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态,等待客户端的连接请求。
2、客户端请求:指客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。
为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。
3、连接确认:当服务器端套接字监听到或者说接收到客户端套接字的连接请求时,就响应客户端套接字的请求,建立一个新的线程(一个新的socket),把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,双方就正式建立连接。
而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。
三、http协议
1、HTTP/0.9 的特性
只支持html标签,只支持纯文本内容。
只有GET一个方法,能请求简单的页面。
2、http/1.0 特性
除支持html标签以外,引入了MIME,可以传纯文本以外的内容;
增加了七个方法,从而增强了访问服务器的方式,使动态网页访问方式更多。
(1)MIME
MIME:multipurpose Internet Mail Extension ,多用途互联网邮件扩展。
在传输前,把非文本数据重新编码为文本格式,接收方用相反的方式将其重新还原为原来的格式,还能调用相应的程序打开此文件。
smtp(简单邮件传输协议): 只能传输纯文本邮件。
在smtp中引入了MIME后可以传输多种文件了。如图像、视频等。
将MIME引入到http当中,所以现在的网页可以传输丰富的文件。
客户端浏览器向web服务器请求数据--》服务器收到请求把响应的文件组织成一个Html文件传给客户端时,都在前面加了格式类型(如 p_w_picpath/jpg)--》客户端览器收到服务器传回来的html页面时,会利用浏览器中的相应的插件来打开此html页面中包含的文件并展示出来(现在浏览器可以解析几百种文件格式。如果没有这种文件的插件就无法打开,如flash,就需要手工安装插件)
(2)http/1.0的几个方法:
GET:从服务器获取资源到本地
POST:提交
head:
PUT:
DELETE:远程从服务器端删除某文件。
trace:
options
connection
(3)动态网页的执行过程:
服务器端存储的文档非Html格式,而是编程语言开发的脚本。服务器端脚本接受参数之后(客户端通过get方法或post方法把参数传递到服务器)在服务器运行一次,运行完成之后生成的html格式文档,再把生成的Html文档发给客户端。
动态网页包含动态网页和静态网页。
3、http/1.1
在http/1.1的基础上增加了以下两项功能:
(1)增强了缓存的功能
(2)长连接机制
在http1.0中,一次连接只能作一次http请求,即请求一次,连接一次,请求完成立即断开连接。
http1.1以后,可进行长连接,即可以一次连接多次请求,即请求连接后就不断开,后续请求直接传送。
如果用在请求不是很大的环境中可以很大的提升访问性能,但在访问量大的请况下不建议开启此功能。
4、http报文
(1)请求报文:
//空白行,一定要的
(2)响应报文:
//空白行
状态码:
1xx:纯信息。
2xx:“成功”类的信息。 200,请求资源正常。
3xx:重定向类的信息。 301,永久重定向; 302,临时重定向; 304,没有发生改变。
4xx:客户端错误类信息。 404,请求了一个不存在的文件;
5xx:服务器端错误类的信息。
例:
请求报文:
GET /2.html HTTP/1.1 //GET方法/×××器根文件夹下2.html的内容,为空就是默认网页/协议版本1.1
Host:www.loready.cn
connection:keep-alive //上两行都是头部,主机名是loready,连接类型是长连接。
响应报文:
HTTP/1.1 200 OK //版本号是1.1 /200状态码,即正常/ok即成功。
1.2 asp.net整个访问过程
1、浏览器请求
(1) 浏览器中输入网址访问某网站
(2) 浏览器会把请求的内容封装成Http请求报文发向服务器端
(3) IIS服务器通过http.sys监听请求(http.sys运行在内核中)
(4) 当监听到请求后,会判断请求的网站是否存在,如存在就把请求转到IIS的inetinfo.exe
(5)进程如果是初次运行,当前应用程序池中没有对应工作进程接受请求,会启动W3WP.exe工作进程
(5) 如果是静态网页,w3wp.exe直接读取磁盘静态网页文件返回给客户端
(7)如果是asp.net动态网页(会根据访问报文中的后缀名判断是不是动态网页,如.aspx,ashx等后缀)那么在工作进程w3wp.exe中加载aspnet_isapi.dll这个程序()开启asp.net请求过程。
----------动态数据封装阶段---------------
Aspnet_isapi.dll开始执行,首先加载.net动行时,启动.net应用程序域,调用.net类库。
(8)Aspnet_isapi.dll通过调用IISAPIRuntime.Proce***equest(ecb)方法把把请求数据简单封装成ISAPIWorkerRequest类型的对象wr。(IISAPIRuntime是一个接口,通过实现这个接口的类来调用这个接口的Proce***equest()方法来处理请求)
(9)再把wr对象传递到httpcontext(wr)构造函数中,将其继续封装成httpcontext类的对象。
Httpcontext类中主要有httprequest和httpresponse()方法。
(10)通过调用HttpApplicationFactory.GetApplicationInstance(contex)创建一个HttpApplication对象。然后调用HttpApplication对象Proce***equest()方法开始整个ASP.net处理请求的过程。其实HttpApplication对象就是global.asax这个文件编译后的类对象。创建HttpApplication对象可以说就是创建了global.asax这个文件编译后的结果。
-----------asp.net生命周期,即动态数据处理阶段-------------------------------
.net生命周期包含了19个事件和23步骤,通过这一系列的过程来对请求数据进行验证,判断是否缓存,创建session,创建页面对象,执行页面的proce***equest()方法等处理后把结果返回给客户端。
第二章一般处理程序
一般处理程序(httphandler):是一个实现了ihttphandler的接口的特殊类,每一个实现了ihttphandler的接口的类都能够处理浏览器发来的请求,并做出响应。用HttpContext(请求上下文)类的context对象实现处理浏览器的请求与响应。其中context.request获得浏览器的请求参数,用context.respones响应请求。
1 context.request的成员:
1、 querystring
获取通过get方式传来的数据。
Get传数据的方式:通过url,或者表单的get。
例:
Int age=Convert.ToInt32Context.request.querystring[“txtAge”] //[]中是html页面中要提交数据的标签的name值。
2、 form
Convert.ToInt32Context.request.Fom[“key”]
获取通过post方式传来的数据。
3、 params
客户提交的数据集合。既可用于get,也可用于post。
Convert.ToInt32Context.request.Params[“key”]
4、 context.request.mappath()
把网页文件的相对路径转换成绝对路径。
5、非form标签无法通过get或post传递参数时,可在form表单中加一个hidden域,把hidden的值设成和非form标签值一样,来达到传递参数的目的。如:DIV,table等非form标签。
2 context.respones的成员:
1、 write方法:
直接在页面上输出内容。
Response.write(“hello,word”);
2、 redirect方法:重定向响应代码302
重定向另外一个页面,服务器发送命令让浏览器跳转。
Response.redirect(http://www.baidu.com);
3、 end方法:
结束输出。碰到end方法后,后面程序都不再执行。
context.Response.End();
3 请求数据的方法:
1、 get
get是先参数通过URL传递到服务器,参数值会显示在url栏中。服务器中的一般处理程序(ashx)通过context.request获得请求的参数值,然后用context.response把处理的结果返回给客户端浏览器。也可以通过表单中的get传递参数。
2、 post
post请求报文中有content-type(请求体类型),且没有缓存的。一般用在登录界面,或者提交的参数数据比较大的地方。
注意事项:
只有表单元素,并且具有name属性才能提交。
具有disable属性不能提交。
当有多个控件的Name属性的值相同时,就会用逗号分隔开数据显示出来。
第三章状态传递和保持
Web应用程序是使用HTTP协议传输数据的。HTTP协议是无状态的协议。一旦数据交换完毕,客户端与服务器端的连接就会关闭,再次交换数据需要建立新的连接。这就意味着服务器无法从连接上跟踪会话。即用户A购买了一件商品放入购物车内,当再次购买商品时服务器已经无法判断该购买行为是属于用户A的会话还是用户B的会话了。要跟踪该会话,必须引入一种机制。
1、 cookies
(1)cookies的机制
如果你把Cookies看成为http协议的一个扩展的话,理解起来就容易的多了,其实本质上cookies就是http的一个扩展。有两个http头部是专门负责设置以及发送cookie的,它们分别是Set-Cookie以及Cookie。当服务器返回给客户端一个http响应信息时,其中如果包含 Set-Cookie这个头部时,意思就是指示客户端建立一个cookie,并且在后续的http请求中自动发送这个cookie到服务器端,直到这个 cookie过期。如果cookie的生存时间是整个会话期间的话,那么浏览器会将cookie保存在内存中,浏览器关闭时就会自动清除这个 cookie。另外一种情况就是保存在客户端的硬盘中,浏览器关闭的话,该cookie也不会被清除,下次打开浏览器访问对应网站时,这个cookie就会自动再次发送到服务器端。一个cookie的设置以及发送过程分为以下四步:
由于HTTP是一种无状态的协议,服务器单从网络连接上无从知道客户身份。怎么办呢?就给客户端们颁发一个通行证吧,每人一个,无论谁访问都必须携带自己通行证。这样服务器就能从通行证上确认客户身份了。这就是Cookie的工作原理。Cookie实际上是一小段的文本信息。客户端请求服务器,如果服务器需要记录该用户状态,就使用response向客户端浏览器颁发一个 Cookie。客户端浏览器会把Cookie保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器。服务器检查该 Cookie,以此来辨认用户状态。服务器还可以根据需要修改Cookie的内容。
(2)cookie的属性和特点
cookie的内容主要包括:名字,值,过期时间,路径和域。路径与域一起构成cookie的作用范围。
属 性 名 |
描 述 |
String name |
该Cookie的名称。Cookie一旦创建,名称便不可更改 |
Object value |
该Cookie的值。如果值为Unicode字符,需要为字符编码。如果值为二进制数据,则需要使用BASE64编码 |
int maxAge |
该Cookie失效的时间,单位秒。如果为正数,则该Cookie在maxAge秒之后失效。如果为负数,该Cookie为临时Cookie,关闭浏览器即失效,浏览器也不会以任何形式保存该Cookie。如果为0,表示删除该Cookie。默认为–1 |
boolean secure |
该Cookie是否仅被使用安全协议传输。安全协议。安全协议有HTTPS,SSL等,在网络上传输数据之前先将数据加密。默认为false |
String path |
该Cookie的使用路径。如果设置为“/sessionWeb/”,则只有contextPath为“/sessionWeb”的程序可以访问该Cookie。如果设置为“/”,则本域名下contextPath都可以访问该Cookie。注意最后一个字符必须为“/” |
String domain |
可以访问该Cookie的域名。如果设置为“.google.com”,则所有以“google.com”结尾的域名都可以访问该Cookie。注意第一个字符必须为“.” |
String comment |
该Cookie的用处说明。浏览器显示Cookie信息的时候显示该说明 |
int version |
该Cookie使用的版本号。0表示遵循Netscape的Cookie规范,1表示遵循W3C的RFC 2109规范 |
(3)cookie的特性
Cookie的不可跨域名性
www.google.com颁发的Cookie不会被提交到域名www.baidu.com去。正常情况下,同一个一级域名下的两个二级域名如www.helloweenvsfei.com和p_w_picpaths.helloweenvsfei.com也不 能交互使用Cookie,因为二者的域名并不严格相同。如果想所有helloweenvsfei.com名下的二级域名都可以使用该Cookie,需要设置Cookie的domain参数.
l Cookie的路径
path属性决定允许访问Cookie的路径(ContextPath),不同路径的cookie不能互访。如 /var/www/jpe/下的cookie,不能获取/var/www/mv/下的cookie。如要求可以互访,需要设置路径属性。
l Cookie的安全属性
HTTP协议不仅是无状态的,而且是不安全的。使用HTTP协议的数据不经过任何加密就直接在网络上传播,有被截获的可能。使用HTTP协议传输很机密的内容是一种隐患。如果不希望Cookie在HTTP等非安全协议中传输,可以设置Cookie的secure属性为 true。浏览器只会在HTTPS和SSL等安全协议中传输此类Cookie。下面的代码设置secure属性为true。
Cookie的有效期
Cookie的maxAge决定着Cookie的有效期,单位为秒(Second)
正数:即多久后cookie失效。
负数:关闭浏览器即消失。
0:则表示删除该Cookie
l Cookie的修改、删除
Cookie并不提供修改、删除操作。如果要修改某个Cookie,只需要新建一个同名的Cookie,添加到response中覆盖原来的Cookie。
如果要删除某个Cookie,只需要新建一个同名的Cookie,并将maxAge设置为0,并添加到response中覆盖原来的Cookie。注意是0而不是负数。负数代表其他的意义。读者可以通过上例的程序进行验证,设置不同的属性。
2、 session
(1)session的机制
session机制是一种服务器端的机制,服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存信息。当程序需要为某个客户端的请求创建一个session时,服务器首先检查这个客户端的请求里是否已包含了一个session标识(称为session id),如果已包含则说明以前已经为此客户端创建过session,服务器就按照session id把这个session检索出来使用(检索不到,会新建一个),如果客户端请求不包含session id,则为此客户端创建一个session并且生成一个与此session相关联的session id,session id的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串,这个session id将被在本次响应中返回给客户端保存。保存这个session id的方式可以采用cookie,这样在交互过程中浏览器可以自动的按照规则把这个标识发送给服务器。一般这个cookie的名字都是类似于SEEESIONID。但cookie可以被人为的禁止,则必须有其他机制以便在cookie被禁止时仍然能够把session id传递回服务器。
(2)session的属性
Session的生命周期
Session保存在服务器端。为了获得更高的存取速度,服务器一般把Session放在内存里。每个用户都会有一个独立的Session。如果Session内容过于复杂,当大量客户访问服务器时可能会导致内存溢出。因此,Session里的信息应该尽量精简。
Session在用户第一次访问服务器的时候自动创建。需要注意只有访问JSP、Servlet等程序时才会创建Session,只访问HTML、IMAGE等静态资源并不会创建Session。如果尚未生成Session,也可以使用request.getSession(true)强制生成Session。
Session生成后,只要用户继续访问,服务器就会更新Session的最后访问时间,并维护该Session。用户每访问服务器一次,无论是否读写Session,服务器都认为该用户的Session“活跃(active)”了一次。
Session的有效期
由于会有越来越多的用户访问服务器,因此Session也会越来越多。为防止内存溢出,服务器会把长时间内没有活跃的Session从内存删除。这个时间就是Session的超时时间。如果超过了超时时间没访问过服务器,Session就自动失效了。
Session的超时时间为maxInactiveInterval属性,可以通过对应的getMaxInactiveInterval()获取,通过setMaxInactiveInterval(longinterval)修改。
Session的超时时间也可以在web.xml中修改。另外,通过调用Session的invalidate()方法可以使Session失效。
session对浏览器的要求
虽然Session保存在服务器,对客户端是透明的,它的正常运行仍然需要客户端浏览器的支持。这是因为Session 需要使用Cookie作为识别标志。HTTP协议是无状态的,Session不能依据HTTP连接来判断是否为同一客户,因此服务器向客户端浏览器发送一个名为JSESSIONID的Cookie,它的值为该Session的id(也就是HttpSession.getId()的返回值)。Session 依据该Cookie来识别是否为同一用户。
该Cookie为服务器自动生成的,它的maxAge属性一般为–1,表示仅当前浏览器内有效,并且各浏览器窗口间不共享,关闭浏览器就会失效。
因此同一机器的两个浏览器窗口访问服务器时,会生成两个不同的Session。但是由浏览器窗口内的链接、脚本等打开的新窗口(也就是说不是双击桌面浏览器图标等打开的窗口)除外。这类子窗口会共享父窗口的Cookie,因此会共享一个Session。
注意:新开的浏览器窗口会生成新的Session,但子窗口除外。子窗口会共用父窗口的Session。例如,在链接上右击,在弹出的快捷菜单中选择“在新窗口中打开”时,子窗口便可以访问父窗口的Session。
(3)session常用方法
Session中包括各种方法,使用起来要比Cookie方便得多。Session的常用方法如表1.2所示。
HttpSession的常用方法
方 法 名 |
描 述 |
void setAttribute(String attribute, Object value) |
设置Session属性。value参数可以为任何Java Object。通常为Java Bean。value信息不宜过大 |
String getAttribute(String attribute) |
返回Session属性 |
Enumeration getAttributeNames() |
返回Session中存在的属性名 |
void removeAttribute(String attribute) |
移除Session属性 |
String getId() |
返回Session的ID。该ID由服务器自动创建,不会重复 |
long getCreationTime() |
返回Session的创建日期。返回类型为long,常被转化为Date类型,例如:Date createTime = new Date(session.get CreationTime()) |
long getLastAccessedTime() |
返回Session的最后活跃时间。返回类型为long |
int getMaxInactiveInterval() |
返回Session的超时时间。单位为秒。超过该时间没有访问,服务器认为该Session失效 |
void setMaxInactiveInterval(int second) |
设置Session的超时时间。单位为秒 |
void putValue(String attribute, Object value) |
不推荐的方法。已经被setAttribute(String attribute, Object Value)替代 |
Object getValue(String attribute) |
不被推荐的方法。已经被getAttribute(String attr)替代 |
boolean isNew() |
返回该Session是否是新创建的 |
void invalidate() |
使该Session失效 |
Tomcat中Session的默认超时时间为20分钟。通过setMaxInactiveInterval(intseconds)修改超时时间。可以修改web.xml改变Session的默认超时时间。例如修改为60分钟:
注意:
(4)url重写机制
经常被使用的一种技术叫做URL重写,就是把session id直接附加在URL路径的后面。还有一种技术叫做表单隐藏字段。就是服务器会自动修改表单,添加一个隐藏字段,以便在表单提交时能够把session id传递回服务器。
实际上这种技术可以简单的用对action应用URL重写来代替。
总结:
Cookie类似于去医院看病的病历本,第次去医院都上病历本给医生看来确认你是哪个病人,以前的病症。可设定某一页只能给哪个医生看,还是所有医生都可以看。多长时间不来看病,这页病历就没有效,医生不承认。
而session,相当于医生有一个自已的病历档案,每次病人看病就把那个病人的档案调出来,但是医生需要你拿病历本拿来,用以识别你是哪个病人。
3、 状态保持
第四章:asp.net生命周期
第五章:模板
第六章:服务器控件
第七章:AJAX