什么是www
首先,我们都知道我们生活在网络里,即万维网(www,World Wide Web);
www是一张遍布全球的计算机网络;
web中的所有计算机均可彼此相互通信;
所有的计算机都使用被称为HTTP的通信标准;
www如何工作
Web 信息存储于被称为网页的文档中。
网页是存储于名为 web 服务器的计算机中的文件。
读取网页的计算机可称为 web 客户机。
web 客户机通过名为 web 浏览器的程序来查看页面。
浏览器是如何加载的
当你浏览网页时的情况基本上是这样的:你坐在你的电脑前,并希望看到在网络上某台计算机上的一个文档,而你有这个文档的URL,也就是我们敲在地址栏里面的那个链接,但仅仅这样还是不够的
如果你想要读取那个文件,存储这个文件的计算机必须运行一个web服务器程序,一个web服务器是一个监听来自浏览器的请求,然后执行他们的计算机程序。
也就是说,浏览器与服务器联系并请求服务器传送文件给它,服务器响应并发送文件,浏览器根据文件的类型进行显示
浏览器会直接显示HTML文档,如果HTML文档它包含指向图像,Java小程序,声音剪辑等的内容,浏览器也会从它们所在的服务器请求这些文件(图像,Java小程序,声音剪辑等,这些文件通常在同一台服务器,但并不总是)。值得一提的是,这将是单独的请求,并给服务器和网络添加额外的负载。当用户点击另一个连接的时整个序列就又重新开始了。
这些响应和请求必须是双方能够理解的,就像你说“hello”,“对方就不能说”你好“,所以制定了一个叫HTTP(超文本传输)协议的东西,但是HTTP协议只定义了双方说的内容是什么,并没有说具体的怎么把这些东西传输出去。就好像我们用中文,但是我们用嘴说还是用笔写,还是打字,这是另一种东西,跨越网络传输比特和字节的实际工作是由 TCP和IP协议实现的,也就是说TCP/IP定义具体怎么把内容传输给对方,大多数其他互联网协议如(FTP,Gopher)也是依赖于TCP/IP实现传输的。
首先要解释两个概念,客户端是指任何做网页浏览器一样工作的软件程序(比如app);服务器是指服务器程序,而不是运行服务器软件的计算机
当我点击一个链接,会发生什么?
第一步,解析url
首先,浏览器所要做的就是要查看新文档的URL,看如何取得这个文档。大多数URL有这样的基本形式:
protocol://server/request-URI协议://服务器/请求的URIhttps://libertyindeath.github.io/index.html
protocol : 告诉浏览器如何检索服务器;
server : 告诉浏览器服务器的地址,就是告诉了浏览器去哪里连接服务器;
request-URI : 是Web服务器用来确定该文件的名称。
第二步,发送请求
通常,协议是“http”的。通过HTTP检索文档的浏览器发送以下请求到服务器:
GET /request-URI HTTP/version
version是说用的http哪个版本,不能繁体字跟简体字混用
这里很重要的一点是,这个请求字符串是服务器看到的所有东西。因此服务器并不关心,请求是来自一个浏览器、一个链接检查程序、搜索引擎爬虫或者是你在手动键入这个请求字符串。服务器只是执行请求,并返回结果。
第三步,服务器响应
当服务器接收到HTTP请求,并找到适当的文档就返回它。然而,HTTP响应被要求具有特定的形式。它必须看起来像这样:
HTTP/[VER] [CODE] [TEXT]
Field1: Value1
Field2: Value2
...Document content here...
第一行显示了所使用的HTTP版本,随后是3位数字(HTTP状态代码)和可以给人看的对应于状态码的短语。通常情况下[code] 和[TEXT]为200 OK,这意味着一切运行良好。第一行后面跟着一些所谓的header,包含关于文档的信息。用一个空行结束header,然后后面就跟着文档的内容。下面是一个典型的header:
HTTP/1.0 200 OK
Server: Netscape-Communications/1.1
Date: Tuesday, 25-Nov-97 01:22:04 GMT
Last-modified: Thursday, 20-Nov-97 10:44:53 GMT
Content-length: 6372
Content-type: text/html
...followed by document content...
我们从这个响应头可以的第一行看到,请求成功了。第二行是可选的,并且告诉我们,在服务器运行的Web服务器是Netscape-Communications,1.1版。然后,我们得到了什么服务器当前的日期和文件的最后修改时间,然后是文件的字节大小,最后,最重要的字段是:Content-type。
内容类型(Content-type)字段被浏览器用来判断接收到的文件格式,HTML文件格式是被定义为text/html,text/plain为普通文本,GIF是image/gif等。这样做的优点是,该URL可以具有任意的结尾而浏览器将仍然能得到文档的正确格式并正确解析。
这里有一个重要的概念是,对于浏览器,服务器可以作为一个黑盒子。即:浏览器请求一个特定的文件,服务器要么是正确返回文件或者返回一个错误消息。服务器如何产生文档对浏览器来说仍然是未知的。这意味着服务器程序可以从一个文件中读取、运行一个程序生成,通过分析一些命令配置编译等种种方式生成这个文档。这使服务器管理员有很大的自由尝试各种不同的服务,因为用户不关心(甚至不知道)他看的的页面是如何生成的。
服务器干嘛的
当服务器被配置好的时候,它通常被配置到磁盘上的某个地方使用一个目录作为其根目录,并且每个目录会有一个默认的文件名(例如index.html)。这意味着,如果你向服务器请求文件“/”(如http://www.domain.tld/),你会获得在服务器根目录下的index.html文件。通常情况下,请求/foo/bar.html,服务器会给你服务器根目录下的foo的目录中的bar.html文件。
通常情况下是这样的。但是也可以将服务器的/foo/映射到其他磁盘或者其他目录上,甚至可以使用服务器端程序来回答对这个目录中的所有请求。服务器甚至可以完全不映射请求到一个目录结构,而可以使用一些其他的方案。
HTTP版本
到目前为止,有三个版本的HTTP。第一个是HTTP/0.9,这是最原始,从来没有真正成为任何标准的规定。而HTTP/1.0,它已作为在RFC1945标准发布。HTTP/1.0是HTTP版本是今天普遍使用(通常与一些1.1的扩展),而HTTP/0.9基本没有被浏览器使用。
RFC 2068描述了HTTP/1.1,它延伸并在若干方面改进HTTP/1.0 ,和1.0的主要区别是默认采用持久连接,让客户端请求的连接打开后进行保持,使其不必重新建立下一个请求,如果几次请求必须迅速发出,这样可以节省一些等待时间和服务器负载。
HTTP/1.1相较于HTTP/1.0协议的区别主要体现在:
- 缓存处理
- 带宽优化及网络连接的使用
- 错误通知的管理
- 消息在网络中的发送
- 互联网地址的维护
- 安全性及完整性
客户端发送请求
基本上,所有的请求看起来像这样:
[METH] [REQUEST-URI] HTTP/[VER]
[fieldname1]: [field-value1]
[fieldname2]: [field-value2]
[request body, if any]
METH(用于请求方法)给出了请求使用的方法,这里有几种请求方法,并且都做不同的事情。在上述的例子中使用的GET,但下面还有一些说明。REQUEST-URI是文档的服务器上的标识,如/index.html或什么的。VER是HTTP版本,就像在上面介绍的服务器的响应头中,下面的header和之前说服务器响应中一样的
请求体仅用于将数据传输到服务器的请求,比如POST和PUT。
GET:取得一个文档
有几个请求的类型,最常见的一种是GET。GET请求基本意思是“给我这个文件”,看起来像这样:GET document_path HTTP/VER。对于URL http://www.yahoo.com/ 的document_path将是/,对于 http://www.w3.org/Talks/General.html 它是/Talks/General.html。
不过,这第一行通常不是一个客户端(UA)唯一发送的请求,但它是唯一要紧的,必不可少的。UA可以包括多个报头字段(header field)的请求给服务器发送信息。这些字段的格式为fieldname: value,并都放在第一个请求行之后单独的行中。
一些GET可以使用的报头字段是:
- User-Agent 标识用户代理
- Referer 告诉服务器用户从哪里来
- If-Modified-Since 主要用来检查cache是否过期
把所有这些碎片拼凑起来:下面是一个典型的GET请求,由我的浏览器(Opera)的发放:
GET / HTTP/1.0
User-Agent: Mozilla/3.0 (compatible; Opera/3.0; Windows 95/NT4)
Accept: */*
Host: birk105.studby.uio.no:81
HEAD:检查文件
有人有时候可能要查看特定文件由服务器返回的头,而无需实际下载的文件。这正是HEAD请求方法提供。HEAD工作原理和GET完全一样,区别只在于服务器只返回头而不是文件内容。
这对像连接检查器这样的程序来说来说就很有用,他们只需要服务器返回的响应头和不需要文件内容。
由服务器返回的响应
概要
服务器返回的响应包括含状态码的一行,报头字段的列表,一个空行,然后是请求的文档(如果有的话)。有点像这样:
HTTP/1.0 code text
Field1: Value1
Field2: Value2
...Document content here...
状态代码
1XX:仅表示信息,没有1XX状态代码的定义,它们只保留给实验目的。
2XX:成功 其他的2xx状态码的其余部分主要是供脚本处理和不经常使用。
“200” ; 服务端成功接收并处理了客户端的请求。
3XX:重定向(关于重定向我之后会专门写一篇文章来介绍
“301” ; 客户端所请求的URL已经移走,需要客户端重定向到其它的URL;
“304” ; 客户端所请求的URL未发生变化;
4XX:客户端错误
“400” ; 客户端请求错误;
“403” ; 客户端请求被服务端所禁止;
“404” ; 客户端所请求的URL在服务端不存在;
5XX:服务器错误
“500” ; 服务端在处理客户端请求时出现异常;
“502” ; 此为中间代理返回给客户端的出错信息,表明服务端返回给代理时出错;
“503” ; 服务端由于负载过高或其它错误而无法正常响应客户端请求;
“504” ; 此为中间代理返回给客户端的出错信息,表明代理连接服务端出现超时。
响应头字段
下面列出了一些常用的字段,更多的请参考相关文档
- Location
- Server
- Content-length
- Content-type
- Content-encoding
- Expires
- Last-modified
缓存:服务器和客户端之间的代理
浏览器缓存The browser cache
你可能已经注意到,当你点击你不太久之前浏览过的页面时候,打开速度比之前更快很多。这是因为浏览器第一次下载这个页面时就在本地存储了一个副本。这个被保存的本地副本就称之为缓存。通常浏览器会设置有浏览器缓存的最大尺寸和文件的最大缓存时间。
这意味着,当一个新的网页被浏览器访问、并存储在缓存中的时候,如果缓存满了(接近最大限制),浏览器就会删除它认为近期不太可能被再次被访问的一些文件,腾出缓存空间。此外,如果你去访问存储在缓存中的网页,浏览器可能会发现,这个页面设置的最大缓存时间是7天,而从上次访问到现在已经过去了8天,所以这个网页需要重新从服务器加载,即使缓存中有它的副本。
究竟缓存是如何工作的,浏览器之间有些差异,但是上面是基本的想法,而且也是一个很好的想法,因为它不仅为用户节省了时间,也减少了网络流量。浏览器的缓存涉及到一些HTTP细节,将稍后介绍。
代理缓存Proxy caches
浏览器缓存是一个不错的功能,但是当很多用户访问同一个网站,就会有很多浏览器从这个网站不断的下载更新缓存,显然这不是最优的方法。
解决的办法是让用户共享缓存,这正是代理缓存做的事情。浏览器还是有它自己的缓存,只不过不在浏览器缓存里的文件的HTTP请求并不是直接发送到服务器了,而是发送到代理缓存。如果代理缓存里面存储了这个文件,它会直接返回给浏览器,如果没有代理缓存会把这个请求转发到服务器请求下载这个文件到代理缓存中然后返回给浏览器。
所以,代理缓存就是很多用户共享的一个共同的缓存,可以显著的减少网络流量压力。但是代理缓存会扭曲基于日志的分析。
一个更好的解决办法就是用一个层级架构的代理缓存系统,而不仅仅只使用单独的一个代理缓存。想象一下,一个大型的ISP为国家的每个区域设立一个代理缓存,让这些区域级的代理缓存共享一个国家级的代理缓存,而不是直接访问源服务器;这种解决方案可以更进一步的减少网络流量。
服务器端编程
服务器端编程是什么以及干什么
服务器端的脚本或程序就是运行在Web服务器上,响应来自客户端请求的程序。这些脚本产生正常的HTML(有时也可以是HTTP头)作为输出,然后反馈给客户端,就好像客户端是请求一个普通页面一样。其实,没有办法让客户端软件判断服务器是否使用了脚本程序。
如JavaScript、VBSctrip和Java Applet等运行于客户端的技术,并不是服务器端脚本的例子。服务器端的脚本和客户端脚本的很大区别是客户端程序和服务器程序运行在不同的机器上,所以,如果一个程序处理的数据全都位于服务器机器上,那么它就应该是服务器端的脚本而不是客户端脚本。如果程序需要经常和用户进行交互,那么使用基于客户端的技术更好,这样可以减少向服务器发送请求。
所以,一般情况下,需要大量数据处理和很少交换的程序应该基于服务器开发;而处理少量数据和频繁交互的程序应该放在客户端。
还有一种情况经常被遗漏的就是,如果你需要一个程序处理数据也需要很多用户交互该如何做?近在眼前的有一种叫XML的技术,这里就不做深入了。
它是如何工作的
根据使用的技术的不同,服务器端脚本的具体细节和工作原理有很大不同,而且有很多技术可以使用。但是,有些东西是不变的:服务器收到一个请求,但是需要注意的是,请求的URL并不对应于一个通常的文件,而是映射到一个脚本程序。
然后服务器启动这个脚本程序,把请求头提供信息和URL全部传给脚本程序,脚本程序运行并产生HTML文档和HTTP响应头,然后服务器把它返回给客户端。
CGI
通用网关接口(CGI,Common Gateway Interface)是一种Web服务器和服务器端编程进行交互的方式。CGI完全独立于编程语言,操作系统和Web服务器。目前,它是最常见的服务器端编程技术,几乎每一个Web服务器都支持。此外,所有服务器用几乎同样的方式实现它,这样你可以为一个服务器编写CGI脚本,然后分发到任何Web服务器上运行。
就像上面说的,服务器需要一种方法来知道哪些URL映射到脚本而其中另一些URL只映射到普通的HTML文件。对于CGI通常是通过在服务器上创建CGI目录。具体做是在服务器进行设置,并告诉服务器,当请求一个特定的顶层目录下的文件时就执行这些CGI脚本(位于磁盘上的某个地方)。(缺省目录通常是/ cgi-bin/,所以一看就知道,像这样的URL:http://www.varsity.edu/cgi-bin/search指向一个CGI脚本,需要注意的是可以任意设定该目录。)有些服务器也可以设置为不使用CGI目录,而要求所有的CGI程序都用已.cgi结尾的文件名。
CGI程序只是普通的可执行程序(或解释性程序,比如Perl或Python,只要服务器知道如何启动程序),因此你可以使用几乎任何你想要的编程语言。在CGI程序被Web服务器启动之前,web服务器定义了一些包含从请求中接收到的信息的变量。这方面的例子有客户端的IP地址,请求头等,如果请求的URL中包含一个问号(?),那么问号之后的一切都会设置成变量。
这意味着,关于请求的额外信息可以被放入该URL的链接。这是像点击计数器用来判断是哪些项目被点击的常用方法之一。因此,用户可以在他/她的页面插入一个图像,并具有SRC属性是一个链接到这样的CGI脚本:SRC =http://stats.vendor.com/cgi-bin/counter.pl?username 。那么脚本就可以知道哪些用户被击中,增量和显示正确的计数。
CGI输出其返回(HTTP头和HTML文档)到服务器的方式是非常简单的:它把它写到标准输出。换句话说,在一个Perl或Python的脚本中,你只需要使用print语句。在C语言中使用printf或者一些等效的函数(C++使用cout«),而Java将使用System.out.println。
其他技术
CGI不是进行服务器端编程的唯一途径,且一直为人诟病低效率。有时候确实是那样,因为每次请求CGI程序就会重新被加载到内存然后执行。一个更快的替代方案是直接使用服务器API本身进行编程,即让程序成为服务器进程的一部分,直接利用提供的API来完成工作,这样当然是服务器相关的,而且如果使用像c/c++(通常都是)导致的程序错误可能使整个服务器崩溃。
基于服务器API编程的主要优点在于,当请求到达时,程序和需要的数据已经在内存中,这样确实会快很多。
有些服务器允许不会导致崩溃的脚本语言。一个例子是AOLserver的,它采用TCL。也有可用的服务器,比如Apache,它让你可以使用Perl或Python进行服务器的API编程,有效地消除了因编程错误引起服务器崩溃的风险。
也有很多很多专利的(和非专有)脚本语言和技术,以及各种web服务器。一些最有名的是ASP,MetaHTML和PHP3。
网友评论