Skip to content

2. Web 编程基础

本章的主要目的是帮助读者了解Web编程的基本原则,这些原则与具体实现所采用的技术无关。本章提供了许多示例,建议读者亲自测试,以便逐步“领悟”Web开发的理念。已经掌握这些知识的读者可以直接跳到下一章。

Web 应用程序的组成部分如下:

Image

编号
作用
常见示例
1
OS 服务器
Unix、Linux、Windows
2
Web 服务器
Apache(Unix、Linux、Windows)
IIS (Windows + .NET 平台)
Node.js(Unix、Linux、Windows)
3
在服务器端执行的代码。它们可以由服务器模块或服务器外部的程序(CGI)执行。
JAVASCRIPT (Node.js)
PHP (Apache, IIS)
JAVA(Tomcat、Websphere、JBoss、Weblogic 等)
C#, VB.NET (IIS)
4
数据库——该数据库可以位于运行程序的同一台机器上,也可以通过互联网位于另一台机器上。
Oracle (Linux, Windows)
MySQL (Linux, Windows)
Postgres (Linux, Windows)
SQL Server (Windows)
5
OS 客户端
Unix、Linux、Windows
6
网页浏览器
Chrome、Internet Explorer、Firefox、Opera、Safari 等
7
在浏览器中运行的客户端脚本。这些脚本无法访问客户端的磁盘
JavaScript(所有浏览器)

2.1. 基于表单的Web应用程序中的数据交换

Image

编号
角色
1
浏览器首次请求 URL 时,请求的是 (http://machine/url)。未传递任何参数。
2
Web 服务器向其发送了该 URL 的网页。 该页面可以是静态的,也可以由服务器脚本(SA)动态生成,该脚本可能使用了数据库中的内容(SB、SC)。 在此,脚本将检测到 URL 被请求时未传递参数,并生成初始网页。
浏览器接收该页面并进行显示(CA)。浏览器端的脚本(CB)可能已修改了服务器发送的初始页面。 随后,通过用户(CD)与脚本(CB)之间的交互,网页将被修改。特别是表单将被填写。
3
用户提交表单数据,这些数据随后将被发送至Web服务器。 浏览器将重新请求初始的URL页面(或根据具体情况请求其他页面),并同时将表单值传输给服务器。为此,它可以使用两种方法,即GET和POST。 收到客户端请求后,服务器将触发与所请求的URL关联的脚本(SA),该脚本将检测参数并进行处理。
4
服务器返回由程序生成的网页(SA、SB、SC)。此步骤与前面的步骤2完全相同。后续交互将按照步骤2和步骤3进行。

2.2. 静态网页、动态网页

静态网页由文件 HTML 表示。动态网页是由 Web 服务器“即时”生成的 HTML 页面。

2.2.1. 静态页面 HTML(HyperText 标记语言)

让我们使用 Visual Studio Express 2012 构建第一个 Web 项目。使用 [Fichier / Nouveau projet] 选项:

  • 在 [1] 中,指定要构建一个空的 ASP.NET 应用程序;
  • 在 [2] 中,指定 Visual Studio 解决方案的名称。本文档中的所有示例都将位于同一个解决方案中;
  • 在 [3] 中,指定即将创建的项目的父文件夹;
  • 在 [4] 中,输入项目名称。

点击确认。

生成的项目位于 [5]。我们将利用它来阐释 Web 编程的基本原理。

首先创建一个静态页面 HTML:

  • 在 [1] 中,右键单击项目,然后按照提示操作;
  • 在 [2] 中,为页面命名;
  • 生成 [3],页面已添加。

创建的页面内容如下:


<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
</head>
<body>

</body>
</html>
  • 第2-10行:代码由根标签<html>限定;
  • 第3-6行:<head>标签界定了所谓的页面头部;
  • 第7-9行:标签<body>界定了所谓的页面主体。

我们将该代码修改如下:


<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>essai 1 : une page statique</title>
</head>
<body>
  <h1>Une page statique...</h1>
</body>
</html>
  • 第 5 行:定义页面标题——将作为显示该页面的浏览器窗口标题显示;
  • 第8行:大号文本(<h1>)。

在浏览器中查看此页面:

  • 在 [1] 中,请求显示该页面;
  • 在 [2] 中,显示的页面 URL;
  • 在 [3] 中,窗口标题——由页面中的 <title> 标签提供;
  • 在 [4] 中,页面正文——由 <h1> 标签提供。

让我们看看 [1],即浏览器接收到的 HTML 代码:

  • 在 [2] 中,浏览器接收到了我们构建的页面 HTML。它对其进行了解析,并将其转换为图形显示。

2.2.2. 一个 ASP.NET 页面

现在我们来创建一个 ASP.NET 页面。这是一个 HTML 页面,其中可能包含服务器端执行的代码,并生成页面的某些部分。我们采用与创建 HTML 页面类似的方法:

  • 在 [1] 中,会调用 ASP.NET 页面;
  • 转换为 [2],为新页面命名;
  • 在 [3] 中,页面已创建。

创建的页面代码如下:


<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="Exemple_00.WebForm1" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
    
    </div>
    </form>
</body>
</html>

我们可以看到之前出现过的 HTML 标签。带有 [runat= "server "] 属性的标签将由服务器处理,并转换为纯 HTML 标签。 因此,上文所示内容与前文静态页面中浏览器将接收的 HTML 代码不同。这被称为动态页面:发送到服务器的 HTML 数据流是由服务器端执行的代码生成的。让我们按以下方式修改该页面:


<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="Exemple_00.WebForm1" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>Démo asp.net</title>
</head>
<body>
  <form id="form1" runat="server">
    <div>
      <h1>Il est <% =DateTime.Now.ToString("hh:mm:ss") %></h1>
    </div>
  </form>
</body>
</html>
  • 第 8 行:为页面设置标题;
  • 第 13 行:显示由 C# 代码生成的文本。该代码位于 <% %> 标签之间。这段 C# 代码以“时:分:秒”的格式显示当前时间。

在浏览器中显示 [1] 该页面:

  • 在 [1] 中,请求显示该页面;
  • 在 [2] 中,显示了所查看页面的 URL;
  • 在 [3] 中,窗口标题——由该页面的 <title> 标签提供;
  • 在 [4] 中,页面正文——由 <h1> 标签提供。

如果刷新页面(F5),我们会看到不同的显示效果(新时间),而 URL 则保持不变。这就是页面的动态特性:其内容会随时间变化。 现在让我们看看浏览器接收到的 HTML 代码:

  • 在 [1] 中,我们可以查看页面的源代码;
  • 在 [2] 中:这次收到的 HTML 代码并非我们构建的,而是由 Web 服务器根据我们的页面 ASP.NET 中的信息生成的。

2.2.3. 结论

综上所述,动态页面与静态页面在性质上有着根本性的差异。

2.3. 浏览器端脚本

HTML 页面可以包含由浏览器执行的脚本。目前(2013年9月),主要的浏览器端脚本语言是 JavaScript。已有数百个基于该语言构建的库,旨在为开发者提供便利。

让我们在已创建的项目中构建一个新的页面 HTML [1]:

编辑文件 [HtmlPage2.html],内容如下:


<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>exemple Javascript</title>
  <script type="text/javascript">
    function réagir() {
      alert("Vous avez cliqué sur le bouton !");
    }
  </script>
</head>
<body>
  <input type="button" value="Cliquez-moi" onclick="réagir()" />
</body>
</html>
  • 第 13 行:定义了一个按钮(type 属性),其文本为“点击我”(value 属性)。点击该按钮时,将执行 JavaScript 函数 [réagir](onclick 属性);
  • 第 6-10 行:一段 JavaScript 脚本;
  • 第 7-9 行:函数 [réagir];
  • 第 8 行:显示一个包含消息 [Vous avez cliqué sur le bouton] 的对话框。

在浏览器中查看页面:

  • 在 [1] 中,显示的页面;
  • [2],点击按钮时显示的对话框。

点击按钮时,不会与服务器进行交互。JavaScript 代码由浏览器执行。

随着大量JavaScript库的出现,现在可以在浏览器中嵌入真正的应用程序。因此,架构正趋向于以下形式:

  • 1-4:服务器 HTML 是一个静态页面服务器 HTML5 / CSS / JavaScript;
  • 5-6:生成的页面 HTML5 / CSS / Javascript 直接与数据服务器交互。该服务器仅提供未经过 HTML 格式化的数据。 由 JavaScript 负责将这些数据插入到浏览器中已存在的页面 HTML 中。

在此架构中,JavaScript 代码可能变得臃肿。因此,我们试图像处理服务器端代码那样将其分层结构化:

  • [UI]层负责与用户交互;
  • [DAO]层负责与数据服务器交互;
  • [métier]层则包含既不与用户交互也不与数据服务器交互的业务流程。该层可能不存在。

2.4. 客户端与服务器的交互

让我们回到最初展示Web应用程序参与者的示意图:

Image

这里我们关注客户端机器与服务器端机器之间的交互。这些交互通过网络进行,有必要回顾一下两台远程机器之间交互的一般结构。

2.4.1. OSI模型

由国际标准化组织(ISO)定义的开放系统互连参考模型(OSI)描述了一个理想网络,其中机器间的通信可通过七层模型来表示:

每一层从下层接收服务,并向上层提供服务。假设位于不同机器A和B上的两个应用程序想要通信:它们在Application层进行通信。 它们无需了解网络运行的所有细节:每个应用程序将想要传输的信息交给下层——即 Présentation 层。因此,应用程序只需了解与 Présentation 层交互的规则即可。 一旦信息进入Présentation层,它就会根据其他规则传递Session层,以此类推,直到信息到达物理介质并被物理传输到目标机器。 到达后,它将经历与在发送方机器上所经历的相反的处理过程。

在每一层,负责发送信息的发送方进程将其发送给另一台机器上属于同一层的接收方进程。这一过程遵循某些规则,即所谓的“该层协议”。因此,最终的通信图示如下:

各层的作用如下:

物理层
负责在物理介质上传输比特。 该层包含数据处理终端设备(E.T.T.D.),如终端或计算机,以及数据电路终端设备(E.T.C.D.),如调制解调器、多路复用器和集中器。该层的主要关注点包括:
  • 信息编码方式的选择(模拟或数字)
  • 传输模式的选择(同步或异步)。
数据链路层
隐藏物理层的物理特性。检测并纠正传输错误。
网络
管理通过网络发送的信息应遵循的路径。这被称为routage:确定信息应遵循的路径,以便其到达接收方。
传输
允许两个应用程序之间进行通信,而之前的层仅支持机器之间的通信。该层提供的一项服务可能是多路复用:传输层可以利用同一条网络连接(机器到机器)来传输属于多个应用程序的信息。
会话
该层提供了一系列服务,使应用程序能够在远程机器上建立并维持工作会话。
表示层
该层旨在统一不同机器上的数据表示形式。因此,来自机器A的数据将在发送至网络前,由机器A的Présentation层按照标准格式进行“包装”。 数据到达目标机器B的Présentation层后,该层将通过标准格式识别这些数据,并以另一种方式进行包装,以便机器B上的应用程序能够识别它们。
应用程序
在此层级,通常存在与用户密切相关的应用程序,例如电子邮件或文件传输。

2.4.2. TCP/IP 模型

OSI 模型是一个理想的模型。TCP/IP 协议套件以如下形式接近该模型:

  • 网络接口(计算机的网卡)承担 OSI 模型中第 1 层和第 2 层的功能
  • IP层(互联网协议)承担第3层(网络层)的功能
  • TCP层(传输控制协议)或UDP层(用户数据报协议)承担第4层(传输层)的功能。 TCP协议确保机器之间交换的数据包能够顺利到达目的地。如果未能到达,它会将丢失的数据包重新发送。 UDP协议不承担此项工作,因此需要由应用程序开发人员来处理。正因如此,在并非100%可靠的互联网环境中,TCP协议才是最常用的。 因此,我们称之为 TCP-IP 网络。
  • 应用层涵盖了 OSI 模型中第 5 至第 7 层的功能。

Web 应用程序位于 Application 层,因此基于 TCP-IP 协议。 客户端和服务器端的 Application 层之间交换消息,这些消息由模型的第 1 至第 4 层负责转发至目的地。为了相互理解,两台机器的应用程序层必须“使用”相同的语言或协议。 Web应用程序所使用的协议名为HTTP(HyperText传输协议)。这是一种文本型协议,即c.a.d,机器通过在网络上交换文本行来实现互通。 这些交互是标准化的,即客户端拥有若干消息来向服务器精确表达其需求,而服务器也拥有若干消息向客户端返回响应。这种消息交互的形式如下:

Image

客户端 --> 服务器

当客户端向Web服务器发出请求时,它会发送

  1. 格式为 HTTP 的文本行来表明其需求;
  2. 一行空行;
  3. 可选地,一个文档。

服务器 --> 客户端

当服务器向客户端发送响应时,它会发送

  1. 格式为 HTTP 的文本行,以说明其发送的内容;
  2. 一行空行;
  3. 可选地发送一个文档。

因此,双向通信采用相同的格式。在两种情况下,都可能发送文档,尽管客户端向服务器发送文档的情况较为罕见。 但 HTTP 协议对此有所规定。这使得,例如,互联网服务提供商的用户能够将各种文档下载到由该服务商托管的个人网站上。交换的文档可以是任意类型的。以浏览器请求包含图片的网页为例:

  1. 浏览器连接到Web服务器并请求所需的页面。所请求的资源通过URL(统一资源定位符)进行唯一标识。浏览器仅发送HTTP头部信息,而不发送任何文档。
  2. 服务器向其响应。它首先发送 HTTP 头部,表明将发送何种类型的响应。如果请求的页面不存在,则可能返回错误。 如果页面存在,服务器将在响应的 HTTP 标头中说明,随后将发送一个 HTML 文档(HyperText 标记语言)。 该文档由一系列 HTML 格式的文本行组成。HTML 文本包含标签(标记),这些标签向浏览器提供如何显示文本的指示。
  3. 客户端根据服务器的 HTTP 标头得知,它将收到一个 HTML 文档。 它将分析该文档,并可能发现其中包含图片引用。这些图片并不在 HTML 文档中。因此,它向同一台 Web 服务器发出新的请求,以获取所需的第一个图片。该请求与步骤 1 中的请求完全相同,只是请求的资源不同。 服务器将处理此请求,向客户端发送所请求的图片。此次,在响应中,HTTP的头部信息将明确指出所发送的文件是一张图片,而非HTML文档。
  4. 客户端接收所发送的图像。步骤3和4将不断重复,直到客户端(通常是浏览器)获取到所有能够完整显示该页面的文档为止。

2.4.3. HTTP协议

让我们通过示例来了解 HTTP 协议。浏览器和 Web 服务器之间交换什么?

Web服务或HTTP服务是一种TCP-IP服务,通常运行在80端口上。它也可能运行在其他端口上。在这种情况下,客户端浏览器必须在其发出的URL请求中明确指定该端口。 一个 URL 请求的一般格式如下:

协议://服务器/路径/信息

其中

协议
为 Web 服务。浏览器也可作为 FTP、新闻、Telnet 等服务的客户端。
服务器
提供 Web 服务的机器名称
端口
Web 服务的端口。如果端口号为 80,则可以省略端口号。这是最常见的情况
路径
指向所请求资源的路径
信息
提供给服务器的补充信息,用于明确客户端的请求

当用户请求加载 URL 时,浏览器会做什么?

  1. 它会与 URL 文件中 machine[:port] 部分指定的机器和端口建立 TCP-IP 通信。 建立 TCP-IP 通信,即是在两台机器之间创建一条通信“管道”。一旦该管道建立,两台机器之间交换的所有信息都将通过它传输。 创建这条通道TCP-IP尚不涉及Web协议HTTP。
  2. TCP-IP通道建立后,客户端将向Web服务器发起请求,并通过发送HTTP格式的文本行(即命令)来完成。它会向服务器发送URL中的路径/信息部分
  3. 服务器将通过同一管道以相同方式进行响应
  4. 双方中的一方将决定关闭该通道。这取决于所使用的 HTTP 协议。 在 HTTP 1.0 协议下,服务器会在每次响应后关闭连接。这迫使需要多次请求以获取构成网页的各个文档的客户端,在每次请求时都必须建立新的连接,从而产生额外开销。 在 HTTP/1.1 协议下,客户端可以指示服务器保持连接开放,直到客户端要求关闭为止。因此,客户端可以通过单次连接获取网页的所有文档,并在获取最后一个文档后自行关闭连接。服务器将检测到此关闭操作,并随之关闭连接。

为了了解客户端与Web服务器之间的交互,我们将使用第1.3节中安装的Chrome浏览器扩展程序[Advanced Rest Client]。我们将处于以下情况:

Image

Web 服务器可以是任意一个。我们在此旨在探索浏览器与 Web 服务器之间将发生的交互。此前,我们创建了以下静态页面 HTML:


<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>essai 1 : une page statique</title>
</head>
<body>
  <h1>Une page statique...</h1>
</body>
</html>

并在浏览器中查看其效果:

 

可见,被请求的 URL 为:http://localhost:56376/HtmlPage1.html。因此,Web 服务器的机器为 localhost(=本地机器),端口为 56376。 现在使用 [Advanced Rest Client] 应用程序请求相同的 URL:

  • 在 [1] 中,启动应用程序(在 Chrome 新标签页的 [Applications] 标签页中);
  • 在 [2] 中,选择 [Request] 选项;
  • 在 [3] 中,指定要查询的服务器:http://localhost:56376;
  • 在 [4] 中,指定所需的 URL:/HtmlPage1.html;
  • 在 [5] 中,为 URL 添加可能的参数。此处无;
  • 在 [6] 中,需指定用于该请求的 HTTP 命令,此处为 GET。

由此得到以下查询:

如此准备好的请求 [7] 由 [8] 发送至服务器。随后获得的响应如下:

我们在前面提到,客户端与服务器的交互采用以下形式:

Image

  • 在 [1] 中,可以看到浏览器在其请求中发送的 HTTP 头部。它没有文档可发送;
  • 在 [2] 中,可以看到服务器在响应中发送的 HTTP 头部。在 [3] 中,可以看到服务器发送的文档。

在 [3] 中,我们可以识别出我们放置在 Web 服务器上的静态页面 HTML。

让我们来分析浏览器的请求 HTTP:

1
2
3
4
5
6
GET /HtmlPage1.html HTTP/1.1 
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.66 Safari/537.36
Content-Type: text/plain; charset=utf-8 
Accept: */*
Accept-Encoding: gzip,deflate,sdch
Accept-Language: fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4
  • 第 1 行未由应用程序显示;
  • 第 2 行:浏览器通过 [User-Agent] 标头进行身份识别;
  • 第3行:浏览器表示其向服务器发送了一个格式为UTF-8的纯文本(text/plain)文档。实际上,此处浏览器并未发送任何文档;
  • 第 4 行:浏览器表示接受任何类型的响应文档;
  • 第5行:浏览器明确了可接受的文档格式;
  • 第6行:浏览器按优先顺序列出了所需的语言。

服务器通过发送以下 HTTP 头部信息进行了响应:

HTTP/1.1 304 Not Modified 
Accept-Ranges: bytes 
Server: Microsoft-IIS/8.0 
X-SourceFiles: =?UTF-8?B?RDpcZGF0YVxpc3RpYS0xMzE0XGFzcG5ldFxkdnBcRXhlbXBsZXNcRXhlbXBsZS0wMFxIdG1sUGFnZTEuaHRtbA==?=
X-Powered-By: ASP.NET
Date: Wed, 18 Sep 2013 15:33:53 GMT 
Content-Type: text/html 
Content-Encoding: gzip 
Last-Modified: Wed, 18 Sep 2013 13:13:19 GMT 
ETag: "b474e0d770b4ce1:0" 
Vary: Accept-Encoding 
Content-Length: 313
  • 第 1 行:未被应用程序显示;
  • 第3行:服务器进行身份识别,此处为微软的IIS服务器;
  • 第 5 行:指示生成响应的技术,此处为 ASP.NET;
  • 第6行:响应的日期和时间;
  • 第7行:服务器发送的文档类型。此处为HTML文档;
  • 第 12 行:所发送文档 HTML 的字节大小。

2.4.4. 结论

我们通过几个示例,了解了Web客户端请求的结构以及Web服务器对其响应的结构。这种交互是通过HTTP协议实现的,该协议是一组由双方交换的文本格式命令。客户端的请求和服务器的响应具有相同的结构,如下所示:

Image

请求资源的两个常用命令是 GET 和 POST。 命令 GET 不附带文档。而命令 POST 则附带文档,该文档通常是一串字符,包含表单中输入的所有值。 命令 HEAD 仅用于请求 HTTP 头部信息,且不附带文档。

应客户端请求,服务器发送的响应具有相同的结构。所请求的资源通过 [Document] 部分传输,除非客户端的命令是 HEAD,在这种情况下,仅发送 HTTP 头部。

2.5. HTML语言的基础

网页浏览器可以显示各种文档,其中最常见的是HTML文档(HyperText标记语言)。该文档是一种使用<balise>texte</balise>格式标签进行格式化的文本。 因此,文本 <B>important</B> 会将重要内容显示为粗体。还有一些独立标签,例如标签 <hr/>,它会显示一条水平线。我们不会详细介绍 HTML 文本中可能出现的标签。 市面上有许多WYSIWYG软件,可让您无需编写任何代码HTML即可构建网页。这些工具会自动生成HTML代码,用于实现通过鼠标和预定义控件设计的版面布局。 因此,用户可以(通过鼠标)在页面中插入一个表格,然后查看软件生成的代码,从而了解在网页中定义表格应使用的标签。这并不复杂。 此外,掌握HTML语言是必不可少的,因为动态Web应用程序必须自行生成HTML代码并发送给Web客户端。该代码由程序生成,当然必须清楚需要生成什么内容,才能让客户端获得其期望的网页。

总而言之,开始进行Web编程时,完全无需掌握HTML语言的全部内容。 不过,掌握该语言是必要的,可以通过使用WYSIWYG网页构建软件(如DreamWeaver及其他数十种同类软件)来学习。 探索HTML语言精妙之处的另一种方法是浏览网页,并查看那些具有有趣特性且您尚未了解的网页的源代码。

2.5.1. 一个示例

请看以下示例,其中展示了网页文档中可能出现的一些元素,例如:

  • 一个表格;
  • 一张图片;
  • 一个链接。

一个 HTML 文档通常具有以下形式:

<html>
    <head>
        <title>标题</title>
        ...
    </head>
    <body 属性>
        ...
    </body>
</html>

整个文档由 <html>...</html> 标签包围。它由两部分组成:

  1. <head>...</head>:这是文档中不可显示的部分。它向将要显示文档的浏览器提供信息。其中通常包含<title>...</title>标签,用于设定浏览器标题栏中显示的文本。此外还可能包含其他标签,特别是定义文档关键词的标签,这些关键词随后会被搜索引擎使用。 该部分还可能包含脚本,通常采用JavaScript或VBScript编写,并将由浏览器执行。
  1. <body 属性>...</body>:这是浏览器将显示的部分。该部分包含的标签会向浏览器指示文档的“预期”视觉呈现形式。每个浏览器都会以自己的方式解释这些标签。 因此,同一网页文档在不同浏览器中的显示效果可能存在差异。这通常是网页设计师面临的难题之一。

我们示例文档的代码如下:


<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>balises</title>
</head>

<body style="height: 400px; width: 400px; background-image: url(images/standard.jpg)">
  <h1 style="text-align: center">Les balises HTML</h1>
  <hr />

  <table border="1">
    <thead>
      <tr>
        <th>Colonne 1</th>
        <th>Colonne 2</th>
        <th>Colonne 3</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>cellule(1,1)</td>
        <td style="width: 150px; text-align: center;">cellule(1,2)</td>
        <td>cellule(1,3)</td>
      </tr>
      <tr>
        <td>cellule(2,1)</td>
        <td>cellule(2,2)</td>
        <td>cellule(2,3</td>
      </tr>
    </tbody>
  </table>

  <table border="0">
    <tr>
      <td>Une image</td>
      <td>
        <img border="0" src="/images/cerisier.jpg"/></td>
    </tr>
    <tr>
      <td>le site de l'ISTIA</td>
      <td><a href="http://istia.univ-angers.fr">ici</a></td>
    </tr>
  </table>
</body>
</html>
标签
标签与示例 HTML
文档标题
<title>标签</title>(第 5 行)
文本 balises 将显示在浏览器的标题栏中,该浏览器将显示该文档
水平条
<hr/>:显示一条水平线(第 10 行)
表格
<table 属性>....</table>:用于定义表格(第 12、32 行)
<thead>...</thead>:用于定义列标题(第 13、19 行)
<tbody>...</tbody>:用于定义表格内容(第20、31行)
<tr 属性>...</tr>:用于定义一行(第 21、25 行)
<td 属性>...</td>:用于定义一个单元格(第 22 行)
示例
<table border="1">...</table>:border 属性定义表格边框的粗细
<td style="width: 150px; text-align: center;">单元格(1,2)</td>:定义一个单元格,其内容为单元格(1,2)。该内容将水平居中(text-align: center)。该单元格宽度为 150 像素(width: 150px)
图片
<img border="0" src="/images/cerisier.jpg"/> (第38行):定义了一张无边框的图片(border="0"),其源文件位于Web服务器上的/images/cerisier.jpg(src="/images/cerisier.jpg")。 该链接位于通过 URL 生成的网页文档中 http://localhost:port/html/balises.htm。 因此,浏览器将请求 URL http://localhost:port/images/cerisier.jpg 以获取此处引用的图片。
链接
<a href="http://istia.univ-angers.fr">此处</a> (第42行):使文本 ici 作为指向 URL http://istia.univ-angers.fr 的链接。
页面背景
<body style="height:400px;width:400px;background-image:url(images/standard.jpg)"> (第 8 行):表示用作页面背景的图片位于 Web 服务器的 /images/standard.jpg 路径下。 在本示例中,浏览器将请求 URL http://localhost:port/images/standard.jpg 以获取该背景图片。此外,文档主体将显示在一个高 400 像素、宽 400 像素的矩形区域内。

从这个简单示例中可以看出,为了构建整个文档,浏览器必须向服务器发出三项请求:

  1. http://localhost:port/html/balises.htm 以获取文档的源文件 HTML
  2. http://localhost:port/images/cerisier.jpg 用于获取图片 cerisier.jpg
  3. http://localhost:port/images/standard.jpg 用于获取背景图片 standard.jpg

2.5.2. 一个表单 HTML

以下示例展示了一个表单:

 

生成此显示效果的代码 HTML 如下:


<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>formulaire</title>
  <script type="text/javascript">
    function effacer() {
      alert("Vous avez cliqué sur le bouton Effacer");
    }
  </script>
</head>

<body style="height: 400px; width: 400px; background-image: url(images/standard.jpg)">
  <h1 style="text-align: center">Formulaire HTML</h1>
  <form method="post" action="FormulairePost.aspx">
    <table border="0">
      <tr>
        <td>Etes-vous marié(e)</td>
        <td>
          <input type="radio" value="Oui" name="R1" />Oui
          <input type="radio" name="R1" value="non" checked="checked" />Non
        </td>
      </tr>
      <tr>
        <td>Cases à cocher</td>
        <td>
          <input type="checkbox" name="C1" value="un" />1
          <input type="checkbox" name="C2" value="deux" checked="checked" />2
          <input type="checkbox" name="C3" value="trois" />3
        </td>
      </tr>
      <tr>
        <td>Champ de saisie</td>
        <td>
          <input type="text" name="txtSaisie" size="20" value="qqs mots" />
        </td>
      </tr>
      <tr>
        <td>Mot de passe</td>
        <td>
          <input type="password" name="txtMdp" size="20" value="unMotDePasse" />
        </td>
      </tr>
      <tr>
        <td>Boîte de saisie</td>
        <td>
          <textarea rows="2" name="areaSaisie" cols="20">
ligne1
ligne2
ligne3
</textarea>
        </td>
      </tr>
      <tr>
        <td>combo</td>
        <td>
          <select size="1" name="cmbValeurs">
            <option value="1">choix1</option>
            <option selected="selected" value="2">choix2</option>
            <option value="3">choix3</option>
          </select>
        </td>
      </tr>
      <tr>
        <td>liste à choix simple</td>
        <td>
          <select size="3" name="lst1">
            <option selected="selected" value="1">liste1</option>
            <option value="2">liste2</option>
            <option value="3">liste3</option>
            <option value="4">liste4</option>
            <option value="5">liste5</option>
          </select>
        </td>
      </tr>
      <tr>
        <td>liste à choix multiple</td>
        <td>
          <select size="3" name="lst2" multiple="multiple">
            <option value="1" selected="selected">liste1</option>
            <option value="2">liste2</option>
            <option selected="selected" value="3">liste3</option>
            <option value="4">liste4</option>
            <option value="5">liste5</option>
          </select>
        </td>
      </tr>
      <tr>
        <td>bouton</td>
        <td>
          <input type="button" value="Effacer" name="cmdEffacer" onclick="effacer()" />
        </td>
      </tr>
      <tr>
        <td>envoyer</td>
        <td>
          <input type="submit" value="Envoyer" name="cmdRenvoyer" />
        </td>
      </tr>
      <tr>
        <td>rétablir</td>
        <td>
          <input type="reset" value="Rétablir" name="cmdRétablir" />
        </td>
      </tr>
    </table>
    <input type="hidden" name="secret" value="uneValeur" />
  </form>
</body>
</html>

视觉控件与标签的映射关系如下:HTML

控件
HTML 标签
表单
<form method="post" action="...">
输入字段
<input type="text" name="txtSaisie" size="20" value="几个字" />
隐藏输入框
<input type="password" name="txtMdp" size="20" value="unMotDePasse" />
多行输入框
<textarea rows="2" name="areaSaisie" cols="20">
行1
行2
行3
</textarea>
单选按钮
<input type="radio" value="是" name="R1" />
<input type="radio" name="R1" value="否" checked="checked" />
复选框
<input type="checkbox" name="C1" value="一" />1
<input type="checkbox" name="C2" value="二" checked="checked" />2
<input type="checkbox" name="C3" value="三" />3
下拉菜单
<select size="1" name="cmbValeurs">
<option value="1">选项1</option>
<option selected="selected" value="2">选项2</option>
<option value="3">选项3</option>
</select>
单选列表
<select size="3" name="lst1">
<option selected="selected" value="1">列表1</option>
<option value="2">列表2</option>
<option value="3">列表3</option>
<option value="4">列表4</option>
<option value="5">列表5</option>
</select>
多选列表
<select size="3" name="lst2" multiple="multiple">
<option value="1">列表1</option>
<option value="2">列表2</option>
<option selected="selected" value="3">列表3</option>
<option value="4">列表4</option>
<option value="5">列表5</option>
</select>
提交按钮
<input type="submit" value="发送" name="cmdRenvoyer" />
重置按钮
<input type="reset" value="重置" name="cmdRétablir" />
按钮
<input type="button" value="清除" name="cmdEffacer" onclick="effacer()" />

让我们来回顾一下这些不同的标签:

2.5.2.1. 表单的

表单

<form method="post" action="FormulairePost.aspx">
HTML标签
<form name="..." method="..." action="...">...</form>
属性
name="frmexemple":表单名称
method="...":浏览器用于将表单中收集的值发送至Web服务器的传输方式
action="...":URL,表单中收集的值将发送至此处。
Web表单由 <form>...</form> 标签包围。表单可以有一个名称(name="xx")。表单中所有控件均遵循此规则。 表单的目的是收集用户通过键盘/鼠标输入的信息,并将这些信息发送至某个 Web 服务器的 URL。具体是哪个?即 action="URL" 属性中指定的那个。 如果缺少该属性,信息将发送至包含该表单的文档所在的URL。Web客户端可以使用两种不同的方法——POST和GET——向Web服务器发送数据。 method="méthode" 属性(其中 method 等于 GET 或 POST) 该标签中的 <form> 属性会告知浏览器,应采用何种方法将表单中收集的信息发送至由 action="URL" 属性指定的 URL。 当未指定 action="method" 属性时,默认采用 action="GET" 方法。

2.5.2.2. 文本输入字段

输入字段
<input type="text" name="txtSaisie" size="20" value="几个字" />
<input type="password" name="txtMdp" size="20" value="unMotDePasse" />
 
标签 HTML
<input type="..." name="..." size=".." value=".."/>
`input` 标签适用于多种控件。正是 type 属性使这些不同的控件能够相互区分。
属性
type="text":指定这是一个文本输入框
type="password":输入框中的字符将被替换为星号(*)。这是它与普通输入框的唯一区别。此类控件适用于密码输入。
size="20":字段中显示的字符数——不限制输入更多字符
name="txtSaisie":控件名称
value="几句话":将在输入框中显示的文本。

2.5.2.3. 多行输入框

多行输入框
<textarea rows="2" name="areaSaisie" cols="20">
第1行
第2行
第3行
</textarea>
 
标签 HTML
<textarea ...>文本</textarea>
显示一个多行输入框,初始内容为文本
属性
rows="2":行数
cols="'20":列数
name="areaSaisie":控件名称

2.5.2.4. 单选按钮

单选按钮
<input type="radio" value="是" name="R1" />
<input type="radio" name="R1" value="否" checked="checked" />
 
HTML 标签
<input type="radio" attribut2="valeur2" ..../>文本
显示一个单选按钮,旁边带有文本
属性
name="radio":控件名称。名称相同的单选按钮构成互斥组:只能选中其中一个。
value="值":分配给单选按钮的值。请勿将此值与单选按钮旁显示的文本混淆,后者仅用于显示。
checked="checked":如果存在此关键字,单选按钮处于选中状态;否则未选中。

2.5.2.5. 复选框

复选框
<input type="checkbox" name="C1" value="un" />1
<input type="checkbox" name="C2" value="二" checked="checked" />2
<input type="checkbox" name="C3" value="三" />3
 
HTML标签
<input type="checkbox" attribut2="value2" ....>文本
显示一个复选框,旁边带有文本
属性
name="C1":控件名称。复选框可以具有相同的名称,也可以不具有相同的名称。具有相同名称的复选框构成一组关联的复选框。
value="值":分配给复选框的值。请勿将此值与单选按钮旁显示的文本混淆。后者仅用于显示。
checked="checked":如果存在此关键字,复选框处于选中状态;否则未选中。

2.5.2.6. 下拉列表(组合框)

下拉列表
<select size="1" name="cmbValeurs">
<option value="1">选项1</option>
<option selected="selected" value="2">选项2</option>
<option value="3">选项3</option>
</select>
 
HTML标签
<select size=".." name="..">
<option [selected="selected"] value=”v”>...</option>
...
</select>
将位于 <option>...</option> 标签之间的文本显示在列表中
属性
name="cmbValeurs":控件名称。
size="1":可见列表项的数量。size="1" 使该列表相当于一个下拉列表框。
selected="selected":如果列表项包含此关键字,该项在列表中将显示为已选中。在上例中,当下拉列表首次显示时,列表项 choix2 将作为下拉列表的选中项显示。
value=”v”:如果该项被用户选中,则向服务器提交的值是 [v]。如果不存在此属性,则向服务器提交的是显示并选中的文本。

2.5.2.7. 单选列表

单选列表
<select size="3" name="lst1">
<option selected="selected" value="1">列表1</option>
<option value="2">列表2</option>
<option value="3">列表3</option>
<option value="4">列表4</option>
<option value="5">列表5</option>
</select>
 
HTML标签
<select size=".." name="..">
<option [selected="selected"]>...</option>
...
</select>
<option>...</option> 标签之间的文本显示在列表中
属性
与仅显示一个项的下拉列表相同。该控件与前一个下拉列表的唯一区别在于其 size>1 属性。

2.5.2.8. 多选列表

单选列表
<select size="3" name="lst2" multiple="multiple">
<option value="1" selected="selected">列表1</option>
<option value="2">列表2</option>
<option selected="selected" value="3">列表3</option>
<option value="4">列表4</option>
<option value="5">列表5</option>
</select>
 
标签 HTML
<select size=".." name=".." multiple="multiple">
<option [selected="selected"]>...</option>
...
</select>
<option>...</option> 标签之间的文本显示在列表中
标签之间的文本
multiple:允许在列表中选择多个元素。在上例中,元素 liste1 liste3 均被选中。

2.5.2.9. button 类型按钮

button 类型按钮
<input type="button" value="清除" name="cmdEffacer" onclick="effacer()" />
 
HTML 标签
<input type="button" value="..." name="..." onclick="effacer()" ..../>
属性
type="button":定义一个按钮控件。还有另外两种类型的按钮,即 submit reset
value="清除":按钮上显示的文本
onclick="函数()":用于定义用户点击按钮时要执行的函数。该函数属于显示的 Web 文档中定义的脚本。上述语法是 javascript 语法。如果脚本使用 vbscript 编写,则应写为 onclick="函数",不带括号。 若需向函数传递参数,语法保持不变:onclick="函数(val1, val2,...)"
在本例中,点击按钮 Effacer 将调用以下 JavaScript 函数 effacer
<script type="text/javascript">
function effacer() {
alert("您已点击了'清除'按钮");
}
</script>
函数 effacer 显示一条消息:

2.5.2.10. 提交按钮

提交按钮
<input type="submit" value="发送" name="cmdRenvoyer" />
 
标签 HTML
<input type="submit" value="发送" name="cmdRenvoyer" />
属性
type="submit":将该按钮定义为将表单数据发送至Web服务器的提交按钮。当客户端点击此按钮时,浏览器将根据<form>标签中method属性定义的方法,将表单数据发送至该标签action属性中定义的URL。
value="提交":按钮上显示的文本

2.5.2.11. 重置按钮

重置按钮
<input type="reset" value="重置" name="cmdRétablir" />
 
HTML 标签
<input type="reset" value="重置" name="cmdRétablir"/>
属性
type="reset":将该按钮定义为表单重置按钮。当用户点击此按钮时,浏览器将把表单恢复到初始接收时的状态。
value="重置":按钮上显示的文本

2.5.2.12. 隐藏字段

隐藏字段
<input type="hidden" name="secret" value="uneValeur" />
标签 HTML
<input type="hidden" name="..." value="..."/>
属性
type="hidden":指定这是一个隐藏字段。隐藏字段是表单的一部分,但不会显示给用户。不过,如果用户要求浏览器显示源代码,就会看到 <input type="hidden" value="..."> 标签,从而看到隐藏字段的值。
value="uneValeur":隐藏字段的值。
隐藏字段有何作用?它可让 Web 服务器在处理客户端的请求时保存信息。以一个 Web 购物应用为例。 客户在目录的首个页面上购买了第一件商品 art1,数量为 q1,随后跳转到目录的另一页面。 为了记住客户已购买了 q1 art1 这两件商品,服务器可以将这两条信息放入新页面 Web 表单中的隐藏字段中。 在该新页面上,客户购买了 q2 和 art2 商品。当该第二个表单的数据被提交(submit)至服务器时,服务器不仅会收到 (q2,art2),还会收到同样作为隐藏字段存在于表单中的 (q1,art1)。 随后,Web服务器将把信息(q1,art1)和(q2,art2)放入一个新的隐藏字段中,并发送新的目录页面。以此类推。

2.5.3. Web客户端向Web服务器提交表单值

我们在前一节中提到,Web客户端有两种方法可将显示的表单值发送至Web服务器:方法GET和POST。让我们通过一个示例来看看这两种方法的区别。

2.5.3.1. 方法 GET

让我们进行一次初步测试,在文档的代码 HTML 中,<form> 标签的定义如下:


<form method="get" action="FormulaireGet.aspx">

当用户点击按钮 [1] 时,表单中输入的值将被发送至页面 ASP.NET [2]。该页面不会对这些参数进行任何处理,而是返回一个空白页面。 我们仅需了解浏览器如何将输入的值传输给Web服务器。为此,我们将使用Chrome中内置的调试工具。通过输入CTRL-I(大写)[3]来激活该工具:

由于我们关注的是浏览器与Web服务器之间的网络通信,因此我们先激活上方的[Network]标签页,然后点击表单中的[Envoyer]按钮。 该按钮属于 [submit] 类型,位于 [form] 标签内。 浏览器响应点击时,会根据[form]标签的[action]属性中指定的URL [FormulaireGet.aspx], 并使用[method]属性中指定的GET方法。随后我们获得以下信息:

上图的屏幕截图显示了在点击 [envoyer] 按钮后,浏览器请求的 URL。 它确实请求了预期的 URL(即 [FormulaireGet.aspx]),但在其后附加了表单中输入的值作为补充信息。若需了解更多详情,请点击上述链接:

在 [1, 2] 上方,我们可以看到浏览器发送的 HTTP 头部信息。此处已对其进行格式化处理。 若要查看这些标头的原始文本,请点击链接 [view source] [3, 4]。完整文本如下:

GET /FormulaireGet.aspx?R1=Oui&C1=un&C2=deux&txtSaisie=programmation+web&txtMdp=ceciestsecret&areaSaisie=les+bases+de+la%0D%0Aprogrammation+web&cmbValeurs=3&lst1=3&lst2=1&lst2=3&cmdRenvoyer=Envoyer&secret=uneValeur HTTP/1.1
Host: localhost:56376
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.111 Safari/537.36
Referer: http://localhost:56376/HtmlFormulaire.html
Accept-Encoding: gzip,deflate,sdch
Accept-Language: fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4

我们发现了一些之前已经出现过的元素。还有一些是首次出现的:

Connection: keep-alive
客户端要求服务器在响应后不要关闭连接。这将允许客户端在后续请求中使用同一连接。连接不会无限期保持打开状态。如果长时间未使用,服务器将关闭该连接。
Referer
URL,即发起新请求时浏览器中显示的页面。

新内容位于 URL 后的信息第 1 行。 可见表单中的选项已反映在 URL 中。用户在表单中输入的值已通过 GET 命令传递:URL?param1=value1&param2=value2&... HTTP/1.1,其中 parami 是 Web 表单控件的名称(name 属性),valeuri 是与其关联的值。 下面是一个三列表格:

  • 第 1 列:列出了示例中控件 HTML 的定义;
  • 第 2 列:显示该控件在浏览器中的显示效果;
  • 第 3 列:显示浏览器针对第 1 列控件发送给服务器的值,该值以示例中 GET 请求中的形式呈现。

控件 HTML


视图


返回值

<input type="radio" value="是" name="R1"/>是
<input type="radio" name="R1" value="否" checked="checked"/>否
R1=是
- 用户选中的单选按钮的 value 属性值。
<input type="checkbox" name="C1" value="一"/>1
<input type="checkbox" name="C2" value="二" checked="checked"/>2
<input type="checkbox" name="C3" value="三"/>3
C1=一
C2=二
- 用户勾选的复选框的 value 属性值
<input type="text" name="txtSaisie" size="20" value="几个词"/>
txtSaisie=Web+编程
- 用户在输入框中输入的文本。空格已被替换为 + 符号
<input type="password" name="txtMdp" size="20" value="unMotDePasse"/>
txtMdp=这是秘密
- 用户在输入框中输入的文本
<textarea rows="2" name="areaSaisie" cols="20">
第1行
第2行
第3行
</textarea>
areaSaisie=Web+编程+基础%0D%0A
Web+编程
- 用户在输入框中输入的文本。%OD%OA 是换行标记。空格已被替换为 + 符号
<select size="1" name="cmbValeurs">
<option value='1'>选项1</option>
<option selected="selected" value='2'>选项2</option>
<option value='3'>选项3</option>
</select>
cmbValues=3
- 用户所选元素的 [value] 属性
<select size="3" name="lst1">
<option selected="selected" value='1'>列表1</option>
<option value='2'>列表2</option>
<option value='3'>列表3</option>
<option value='4'>列表4</option>
<option value='5'>列表5</option>
</select>
lst1=3
- 用户所选元素的 [value] 属性
<select size="3" name="lst2" multiple="multiple">
<option selected="selected" value='1'>列表1</option>
<option value='2'>列表2</option>
<option selected="selected" value='3'>列表3</option>
<option value='4'>列表4</option>
<option value='5'>列表5</option>
</select>
lst2=1
lst2=3
- 用户所选元素的 [value] 属性
<input type="submit" value="发送" name="cmdRenvoyer"/>
 
cmdRenvoyer=发送
- 用于将表单数据发送至服务器的按钮名称及其属性 value
<input type="hidden" name="secret" value="uneValeur"/>
 
secret=一个值
- 隐藏字段的属性 value

2.5.3.2. 方法 POST

我们修改文档 HTML,使浏览器现在使用方法 POST 将表单值发送至 Web 服务器:


  <form method="post" action="FormulairePost.aspx">

我们按照 GET 方法的方式填写表单,并通过 [Envoyer] 按钮将参数提交至服务器。 正如第 34 页上一段所述,我们在 Chrome 中可以查看浏览器发送的请求中的 HTTP 请求头:

POST /FormulairePost.aspx HTTP/1.1
Host: localhost:56376
Connection: keep-alive
Content-Length: 195
Pragma: no-cache
Cache-Control: no-cache
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Origin: http://localhost:56376
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.111 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Referer: http://localhost:56376/HtmlFormulaire.html
Accept-Encoding: gzip,deflate
Accept-Language: fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4

R1=Oui&C1=un&C2=deux&txtSaisie=programmation+web&txtMdp=unMotDePasse&areaSaisie=les+bases+de+la%0D%0Aprogrammation+web%0D%0A&cmbValeurs=3&lst1=3&lst2=1&lst2=3&cmdRenvoyer=Envoyer&secret=uneValeur

客户端的 HTTP 请求中出现了新内容:

POST URL HTTP/1.1
查询 GET 已被查询 POST 取代。 这些参数已不再出现在请求的第一行中。可以看出,它们现在被放置在(第14行)HTTP请求之后,其前有一行空行。它们的编码与GET请求中的编码完全相同。
Content-Length
“发送”的字符数,c.a.d。这是 Web 服务器在收到 HTTP 头部后,为获取客户端发送的文档所需读取的字符数。此处的文档即为表单值的列表。
Content-type
指定客户端在发送完头部信息后将发送的文档类型。类型 HTTP 表示该文档包含表单值。

向 Web 服务器传输数据有两种方法:GET 和 POST。哪种方法更好?我们看到,如果表单值由浏览器通过 GET 方法发送, 浏览器会在其 Adresse 字段中以 URL 的形式显示所请求的 URL?param1=val1&param2=val2&.... 这既可以视为优点,也可以视为缺点:

  • 如果希望允许用户将此带参数的 URL 添加到收藏夹链接中,则视为优点;
  • 若不希望用户访问表单中的某些信息(例如隐藏字段),则属于缺点。

此后,我们在表单中将几乎完全采用 POST 方法。

2.6. Conclusion

本章介绍了Web开发中的若干基础概念:

  • 通过 HTTP 协议进行的客户端-服务器交互;
  • 使用 HTML 语言设计文档;
  • 设计数据输入表单。

我们通过一个示例了解了客户端如何向Web服务器发送信息。但我们尚未介绍服务器如何

  • 检索这些信息;
  • 处理这些信息;
  • 并根据处理结果向客户端发送动态响应。

这是Web编程的范畴,我们将在下一章中通过介绍ASP.NET和MVC技术来探讨这一领域。