HTTP
Web客户端和服务器的交互用的是一个基于文本的应用级协议 —— HTTP(Hypertext Transfer Protocol)。客户端与服务器的一个典型交互过程为:一个Web客户端(即浏览器)打开一个到服务器的因特网连接,并且请求某些内容;服务器响应所请求的内容,然后关闭连接;浏览器读取这些内容,并把它显示在屏幕上。
Web与常规的文件检索服务(如FTP)的主要区别是: Web内容可以使用HTML(Hypertext Markup Language)来编写,提供格式和布局的控制,并且包含超链接。
Web内容
对于Web客户端和服务器而言,内容是与一个MIME(Multipurpose Internet Mail Extensions)类型相关的字节序列。
Web服务器以两种不同的方式向客户端提供内容:
- 取一个磁盘文件,并将它的内容返回给客户端。
- 运行一个可执行文件,并将它的输出返回给客户端。
每条由Web服务器返回的内容都是和它管理的的某个文件相关联的。这些文件中的每一个都有唯一的名字,叫做URL(Universal Resource Locator)。例如:
http://www.google.com:80/index.html
标识因特网主机www.google.com上一个称为/index.html的HTML文件,它是由一个监听端口80的Web服务器管理的。
可执行文件的URL可以在文件名后包括程序参数。?
分隔文件名和参数,而且每个参数都用&
分隔开。例如:
http://example.com:80/cig-bin/adder?123&345
标识了一个叫做/cig-bin/adder的可执行文件,会带两个参数123和345来调用它。在事务过程中,客户端和服务器使用的URL的不同部分。例如,客户端使用前缀
http://www.google.com:80
来决定与哪类服务器联系,服务器在哪,以及它监听的端口号是多少。服务器使用后缀
/index.html
来发现在它的文件系统中的文件,并确定请求的是动态内容还是静态内容。
HTTP事务
HTTP事务是指由客户端发起HTTP请求,服务器返回HTTP响应,然后关闭连接。
1.HTTP请求
HTTP请求的组成:
- 一个请求行(request line)
- (紧跟着)零个或多个请求报头(request header)
- (最后以)一个空的文本行来终止报头列表
- (POST方法可能会在这增加一个请求主体)
每个文本行都由一对回车和换行符结束\r\n
请求行的形式是:
<method> <uri> <version>
<method>
是HTTP支持的方法,包括GET、POST、OPTIONS、HEAD、PUT、DELETE和TRACE。应用最多的GET方法指导服务器生成和返回<URI>
(Uniform Resource Identifier)标识的内容。POST方法经常用于提交表单。HEAD方法类似与GET方法,当服务器接受到HEAD方法的请求时,将会用一个HTTP报文进行响应,但是并不返回请求主体。PUT方法常与Web发行工具联合使用,用户使用它上传对象到指定的Web服务器上的指定路径。DELETE方法允许用户删除Web服务器上的内容。
<uri>
是相应URL的后缀,包括文件名和可选的参数。
<version>
表明了该请求遵循的HTTP版本。
请求报头为服务器提供了额外的信息,例如浏览器的商标名,或者浏览器理解的MIME类型。请求报头的格式为:
<header name>: <header data>
针对HTTP/1.1请求,我们需要HOST报头,如Host: www.google.com
,它的数据指示了原始服务器的域名。
2.HTTP响应
HTTP响应的组成:
- 一个响应行(response line)
- (紧跟着)零个或更多的响应报头(response header)
- (再紧跟着)一个终止报头的空白行
- (再紧跟着)一个响应主体(response body)
一个响应行的格式是:
<version> <status code> <status message>
<version>
描述了响应所遵循的HTTP版本。<status code>
是一个三位的正整数,指明对请求的处理,<status message>
给出与错误码等价的英文描述。以下是一些常见的状态码:
Status Code | Status Message | 描述 |
---|---|---|
200 | 成功 | 处理请求无误 |
301 | 永久移动 | 内容已移至由响应报头Location指明的新URL上 |
400 | 错误请求 | 服务器不能理解请求 |
403 | 禁止 | 服务器无权访问请求的文件 |
404 | 未发现 | 服务器找不到所请求的文件 |
501 | 未实现 | 服务器不支持请求的方法 |
505 | HTTP版本不支持 | 服务器不支持请求的版本 |
状态码分类:1xx消息,2xx成功,3xx重定向,4xx客户端错误,5xx服务器错误
响应报头提供了关于响应的附加信息。比如Content-Type
告诉客户端响应主体中内容的MIME类型;Content-Length
指示响应主体的大小。
终止响应报头的空文本行之后,跟随的是响应主体,响应主体中包含着被请求的内容。
服务动态内容
CGI(Common Gateway Interface)的实际标准用来解决如下问题:
-
客户端如何将参数传递给服务器
Get请求的参数在URL中传递。一个
?
分割文件名和参数,而每个参数都用一个&
字符隔开。参数中不允许有空格,而必须用字符串%20
来表示,对于其他特殊字符,也存在着相似的编码。POST请求的参数是在请求主体中而不是在URI中传递的。 -
服务器如何将参数传递给子进程
在服务器接收到一个如下的请求后
GET /cgi-bin/adder?123&345 HTTP/1.1
它调用
fork
创建一个子进程,并调用execve
在子进程的上下文中执行/cgi-bin/adder
程序。像adder
这样的程序,常常被称为CGI程序,因为它们遵守CGI标准。在调用execve
之前,子进程将CGI环境变量QUERY_STRING
设置为123&345
,adder
程序在运行时可以使用Unixgetenv
函数来引用它。 -
服务器如何将其他信息传递给子进程
CGI定义了大量的环境变量,一个CGI程序在它运行时可以设置这些环境变量。
环境变量 描述 QUERY_STRING 程序参数 SERVER_PORT 父进程监听的端口 REQUEST_METHOD GET或POST REMOTE_HOST 客户端的域名 REMOTE_ADDR 客户端的点分十进制IP地址 CONTENT_TYPE 只对POST而言: 请求体的MIME类型 CONTEMT_LENGTH 只对POST而言: 请求体的字节大小 -
子进程将它的输出发送到哪里
一个CGI程序将它的动态内容发送到标准输出。在子进程中加载并运行CGI程序之前,它使用Unix
dup2
函数将标准输出重定向到和客户端相关联的已连接描述符。因此,任何CGI程序写到标准输出的内容都会直接到达客户端。 因为父进程不知道子进程生成的内容的类型和大小,所以子进程负责生成Content-type
和Content-length
响应报头,以及终止报头的空行。
cookie
HTTP服务器是无状态的,也就是说,同一个用户向一个服务器发送不同的请求,服务器不能识到这些请求来自来自同一个用户。
然而一个Web站点通常希望能够识别用户,为此HTTP使用了cookie。cookie的工作过程为:
- 用户浏览器向服务器发送请求
- 服务器接收的请求后,产生一个唯一的标识码
<identification code>
,并以此为索引在它的后端数据库中产生一个表项 - 服务器用一个包含
Set-cookie: <identification code>
响应报头的响应报文对用户浏览器进行响应 - 用户浏览器收到该HTTP响应报文时,它会看到
Set-cookie
报头,该浏览器在它管理的特定cookie文件中添加一行,改行包含服务器的主机名和在Set-cookie
报头中声明的<identification code>
- 之后当用户浏览器继续向相同服务器发送请求时,HTTP请求报文都包含
Cookie: <identification code>
请求报头,服务器可以据此跟踪用户,保存用户状态
- older
- Newer