赵工的个人空间


专业技术部分转网页计算转业余爱好部分


 编程语言

常用的编程语言
C#编程语言基础
C#面向对象与多线程
C#数据及文件操作
JavaScript基础
JavaScript的数据类型和变量
JavaScript的运算符和表达式
JavaScript的基本流程控制
JavaScript的函数
JavaScript对象编程
JavaScript内置对象和方法
JavaScript的浏览器对象和方法
JavaScript访问HTML DOM对象
JavaScript事件驱动编程
JavaScript与CSS样式表
Ajax与PHP
ECMAScript6的新特性
Vue.js前端开发
PHP的常量与变量
PHP的数据类型与转换
PHP的运算符和优先规则
PHP程序的流程控制语句
PHP的数组操作及函数
PHP的字符串处理与函数
PHP自定义函数
PHP的常用系统函数
PHP的图像处理函数
PHP类编程
PHP的DataTime类
PHP处理XML和JSON
PHP的正则表达式
PHP文件和目录处理
PHP表单处理
PHP处理Cookie和Session
PHP文件上传和下载
PHP加密技术
PHP的Socket编程
PHP国际化编码
MySQL数据库基础
MySQL数据库函数
MySQL数据库账户管理
MySQL数据库基本操作
MySQL数据查询
MySQL存储过程和存储函数
MySQL事务处理和触发器
PHP操作MySQL数据库
数据库抽象层PDO
Smarty模板
ThinkPHP框架
Python语言基础
Python语言结构与控制
Python的函数和模块
Python的复合数据类型
Python面向对象编程
Python的文件操作
Python的异常处理
Python的绘图模块
Python的NumPy模块
Python的SciPy模块
Python的SymPy模块
Python的数据处理
Python操作数据库
Python网络编程
Python图像处理
Python机器学习
TensorFlow深度学习
Tensorflow常用函数
TensorFlow用于卷积网络
生成对抗网络GAN


Ajax与PHP

Ajax提供了一种以异步方式与服务器通信的机制,这种机制是不必刷新整个页面便可以对页面的局部进行更新。应用Ajax使客户端与服务器端的功能划分得更细,客户端只获取需要的数据,而服务器也只为有用的数据工作,从而大大节省了网络带宽、提高网页加载速度和运行效果。
Ajax的处理过程由事件触发,创建一个XMLHttpRequest对象,将HTTP方法和目标URL以及请求返回后的回调函数设置到XMLHttpRequest对象上。通过XMLHttpRequest向服务器发送请求,发送请求后继续响应用户的界面交互,只有等到请求真正从服务器返回时才调用函数,对响应数据进行处理。

1.标准Ajax应用示例:

1)HTML及JavaScript部分:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<title>AJAX Sample</title>
</head>
<body>
<script type="text/javascript">
//处理返回的结果
function getResult() {
  //alert(oXMLHttpRequest.status);
  if(oXMLHttpRequest.status=200) {
try {
   //一旦获取了数据就可以处理这些数据,这里只是演示
   document.write("数据==<xmp>"+oXMLHttpRequest.responseText+"</xmp>");
} catch(err) {
   alert(err.message);
}
  } else if(oXMLHttpRequest.status==404) {
   document.write("没有发现请求的文档!");
  } else if(oXMLHttpRequest.status==500) {
   document.write("服务器内部错误!");
  }
}
//响应状态变化
function theReadyStateChange() {
  //根据HTTP请求的状态码确定当前请求处于什么状态
  if(oXMLHttpRequest.status=0) {
     //对象尚未初始化,这是最初的状态,这时open()方法尚未被调用
     //一段代码处理这个状态
  } else if(oXMLHttpRequest.status==1) {
     //对象已创建,这时还未调用send()方法
     //这时可以给用户一个提示,例如"正在加载,请稍等…"
  } else if(oXMLHttpRequest.status==2) {
     //已经调用send()方法,但响应主体还未到达
  } else if(oXMLHttpRequest.status==3) {
     //与服务器交互过程中,部分数据已经到达,但还不可以访问
  } else if(oXMLHttpRequest.status==4) {
     //全部数据已经到达,数据和报头都可以访问了
     getResult();
  }
  //alert(oXMLHttpRequest.readyState);
}
//首先创建一个XMLHttpRequest对象
var oXMLHttpRequest=new XMLHttpRequest();
//接着马上设置一个函数响应状态变化,这是一个回调函数
oXMLHttpRequest.onreadystatechange=theReadyStateChange;
//打开连接,发送数据,并在这个过程中捕捉错误
try {
   oXMLHttpRequest.open("POST","http://localhost/employees.php",true);
   oXMLHttpRequest.send('<query role="admin" />');
} catch(err) {
   alert(err.message);
}
</script>
</body>
</html>

2)XMLHttpRequest发送的HTTP请求和服务器的响应报头:

下面是XMLHttpRequest发送的:
GET /employees.xml HTTP/1.1
Accept:*/*
Referer:http://localhost/go.html
Accept-Encoding:gzip,deflate
User-Agent:Mozilla/4.0 (compatible;MSIE 6.0;Windows NT 5.1;SV1)
Host:localhost
Connection:Keep-Alive

HTTP/1.1 200 OK
Server:Microsoft-IIS/5.1
Date:Sat,27 Oct 2007 10:16:41 GMT
Content-Type:text/xml
Accept-Ranges:bytes
Last-Modified:Sun,15 Apr 2007 16:56:29 GMT
ETag:"80582c37f7fc71:aad"
Content-Length:537
可以看到,XMLHttpRequest发送的是标准的HTTP请求,使用的方法和属性也可以对返回的HTTP响应作出合适的处理。

3)PHP程序处理Ajax请求和作出响应:

使用PHP程序可以捕捉到Ajax请求并作出处理。如果是GET请求,就像是处理浏览器正常的请求那样;如果是POST请求,就必须使用下面的方法之一获取请求数据:
$xml_str=file_get_contents("php://input");
$xml_str=$GLOBALS['HTTP_RAW_POST_DATA'];
要使用下面一种方法,必须在配置文件中添加下面一行配置:
  always_populate_raw_post_data=On
要对请求作出响应,也像是正常的响应一样,但Ajax的响应数据一般是XML格式或JSON的文档,这便于使用JavaScript进行处理。
当是XML格式数据时,应该定义响应报头,一般就是"Content:text/xml",并且正文是合法的XML文档。示例:
<?php
//下面将输出一个XML文件
header("Content-type:text/xml;charset=utf-8");
$xml_str=file_get_contents("php://input"); //获取请求中的xml字符串
$doc=new DOMDocument();
$doc->loadXML($xml_str); //构造DOM对象,然后处理
$root=$doc->documentElement;
$role=$root->getAttribute("role");
If($role=='admin') { //通过判断决定返回的数据
  echo '<?xml wersion="1.0" encoding="UTF-8" ?>'.'
<employee>'
<!--雇员列表-->
<name EmpType="副代表">
  <first>Leverling</first>
  <last>Janet</last>
</name>
<name EmpType="技术联系人">
  <first>Buchanan</first>
  <last>Steven</last>
</name>
</employee>';
} else {
  echo '<?xml wersion="1.0" encoding="UTF-8" ?>'.'
      '<fault info="权限不正确" />';
}
?>
通过浏览器请求前面创建的HTML网页,那么其中的XMLHttpRequest对象就可以访问该PHP动态网页,并获取数据。

4)编码混乱问题:

在应用XMLHttpRequest时,会发现接收到的响应会出现乱码,这是由于不当的HTTP内容类型报头造成的。由于XMLHttpRequest将响应信息解码为Unicode字符串,所以必须将返回的数据编码为UTF-8,并且设置正确的HTTP响应报头。示例:
<?php
//下面将输出一个XML文件
header("Content-type:text/xml;charset=utf-8");
?>

5)使用代理实现跨域请求:

当在Web浏览器中请求一个网页,而网页中又使用XMLHttpRequest发送请求时,只能请求位于同一超域中任意服务器上的资源,这就是超域匹配规则,它可以避免网页中的XMLHttpRequest从其他人的服务器上下载信息。此限制是为了安全考虑。
下表列出了网页和XMLHttpRequest域匹配关系,x、y、z表示任意主机:


网页网址

对应的超域

XMLHttpRequest网址

http://Myhost

Myhost

http://Myhost

http://Myhost.com

Myhost.com

http://x.Myhost.com

http://x.y.Myhost.com

y.Myhost.com

http://z.y.Myhost.com

http://www.Myhost.com

Myhost.com

http://z.Myhost.com

例如下面的代码,位于网页http://localhost/myPage.html内,而请求的XMLHttpRequest网址却是http://myhost/employee.xml,不在同一个超域内。'
<script type="text/javasript">
var oXMLHttpRequest=new XMLHttpRequest();
try {
  oXMLHttpRequest.open("GET","http://myhost/employees.xml",true);
  oXMLHttpRequest.send(null);
} catch(err) {
  alert(err.message?err.message:err.toString());
}
</script>
那么就会导致出错,浏览器显示出错信息。
在某些特殊情况下,用户需要能够实现跨域请求,那么可以在服务器端创建一个代理服务器来实现。例如,网页proxy.php定义了下面的PHP代码,该网页与myPage.html位于同一个域内,在该PHP网页内读取另一个域myhost内的employee.xml,然后将读取的数据返回给客户端。
<?php
$dataURL="http://myhost/employees.xml";
readfile($dataURL);
?>
那么XMLHttpRequest的请求地址就可以写成下面的形式,通过这个PHP网页作为代理就可以访问位于另一个域内的employees.xml了。
oXMLHttpRequest.open("GET","http://localhost/proxy.php",true);

2.使用JSON编码:

Ajax也经常使用JSON来交换数据。JSON是JavaScript Object Notation的缩写,是一种轻量级的数据交换格式,易于阅读和编写,同时也易于机器解析和生成。
PHP包含几个函数用于JSON格式数据的转换,即序列化和逆序列化,并且定义了几个常量,这些常量经常用作JSON类函数的功能项。见下表:


常量

说明

版本

JSON_ERROR_NONE

表示无错误发生

5.3.0+

ISON_ERROR_DEPTH

表示超出所允许的最大堆栈深度

5.3.0+

JSON_ERROR_CTRL_CHAR

表示控制字符有错误,可能是由于不正确的编码所致

5.3.0+

JSON_ERROR_SYNTAX

表示语法错误

5.3.0+

JSON_HEX_TAG

所有的<和>将被分别转换为\u003C和\u003E

 

JSON_HEX_AMP

所有的&s将被转换为\u0026

 

JSON_HEX_APOS

所有的'将被转换为\u0027

 

JSON_HEX_QUOT

所有的"将被转换为\u0022

 

JSON_FORCE_OBJECT

当编码的是一个非复合数组时,输出一个对象而非数组

 

1)对JSON格式的字符串进行解码:

语法格式:
json_decode(string $json[,bool $assoc=false[,int $depth=512]]);
参数$json定义将被解码的符合JSON格式的字符串;参数$assoc定义是否将解码后所得的PHP对象转换为复合数组,默认为false,表示不转换;参数$depth定义所允许递归的最大深度。自PHP5.3.0始增加了参数$depth,并且允许递归的最大深度从过去的128增加到512。
示例:
<?php
//定义一个符合JSON格式的字符串
$jsontext='{"surname":"zhao","firstname":"dwen"}';
//解码为对象
print_r(json_decode($jsontext));
//解码后所得的PHP对象转换为复合数组
print_r(json_decode($jsontext,true));
?>
解码后的结果如下:
stdClass Object
(
   [surname]=>zhao
   [firstname]=>dwen
)
Array
(
   [surname]=>zhao
   [firstname]=>dwen
)

2)对变量进行JSON编码:

语法格式:
json_encode(mixed $value[,int $options=0]);
参数$value定义被编码为JSON格式字符串的PHP数据类型,除了简单数据类型,也可以是数组、对象等,但资源类型的数据不能被编码。参数$options定义编码的功能,可以是|号分隔的如下常量的组合,JSON_HEX_QUOT、JSON_HEX_TAG、JSON_HEX_AMP、JSON_HEX_APOS、JSON_FORCE_OBJECT。这些常量的具体含义可以参考常量表。
示例:将PHP数组解析为JSON字符串
<?php
//复合数组被编码后所得的JSON字符串在JavaScript中表示为对象
$arr=array("surname"=>"zhao","firstname"=>"dwen");
echo json_encode($arr)."\n";
//索引数组编码后所得的JSON字符串在JavaScript中表示为数组
$arr=array("zhao","dwen");
echo json_encode($arr)."\n";
//也可以强制将索引数组编码为JavaScript对象
echo json_encode($arr,JSON_FORCE_OBJECT)."\n";
?>
编码后的结果分别为:
{"surname":"zhao","firstname":"dwen"}
{"zhao","dwen"}
{"0":"zhao","1":"dwen"}

3)处理解析错误:

语法格式:
json_last_error();
该函数返回JSON函数执行过程中出现的最后一次错误,返回值是一个整数,对应于几个常量,具体含义可以参考常量表。示例:
<?php
//定义一个符合JSON格式的字符串
$jsontext='{"surname":"zhao","firstname":"dwen"}';
//解码为对象
print_r(json_decode($jsontext));
//执行过程中的错误可以使用json_last_error()捕捉
$json_error=json_last_error();
//然后可以判断错误类型
switch($json_error) {
case JSON_ERROR_DEPTH;
    echo '超出所允许的最大堆栈深度!';
    break;
case JSON_ERROR_CTRL_CHAR;
    echo '控制字符有错误!';
    break;
case JSON_ERROR_SYNTAX;
    echo '语法错误!';
    break;
case JSON_ERROR_NONE;
    echo '无错误发生!';
    break;
}
?>

4)客户端数据处理:

当JSON格式的数据传递到客户端,可以使用JavaScript程序来处理,首先使用eval()函数或静态方法JSON.parse()将JSON数据逆序列化为JavaScript数据,然后使用JavaScript处理这些数据。

3.开发jQuery for PHP程序:

jQuery是一个强大的JavaScript框架,重点在于能够实现跨浏览器兼容。例如,由于浏览器对XMLHttpRequest的支持不同,那么就要编写下面的代码来实现浏览器兼容:
<script type="text/javascript">
var oXMLHttpRequest;
if (window.XMLHttpRequest) { //Mozilla Safari IE7 Opera
   oXMLHttpRequest=new XMLHttpRequest();
   if(oXMLHttpRequest.overrideMimeType) {
      oXMLHttpRequest.overrideMimeType('text/xml');
   }
} else if(window.ActiveXObject) { //IE7-
   var progIDs= ["Msxml2.XMLHTTP.5.0", "Msxml2.XMLHTTP.4.0", "MSXML2.XMLHTTP.3.0",
"Msxnl2.XMLHTTP", "Microsoft.XMLHTTP"];
   for (var i=0;i<progIDs.length;i++) {
      try {
         oXMLHttpRequest=new ActiveXObject(progIDs[i]);
      } catch(err) {
         try {
            oXMLHttpRequest=new ActiveXObject("Microsoft.XMLHTTP");
         } catch(err) {}
      }
   }
}
If(!oXMLHttpRequest) {
   alert('不存在适用的XMLHttpRequest');
}
</script>
而jQuery只需使用下面的方法就可以实现XMLHttpRequest的跨浏览器兼容性请求,并可以将返回的数据转换为XML DOM对象:
jQuery.ajax(settings)
jQuery的请求就是Ajax的请求,用户可以使用PHP处理请求并返回响应。当请求成功后,jQuery就会执行回调函数success(),然后就可以处理数据了,这时数据已经被解析为XML DOM对象。示例:
<script type="text/javascript">
jQuery.ajax( {
   type:"POST",
   url:"employees.php",
   data:'<query role="admin" />',
   success:function(msg) {alert(DOM2String(msg));},
   error:function(jqXHR,textStatus,errorThrown){alert(textStatus);}
});
Function DOM2String(doc) {
   try {
      if(window.ActiveXObject) {
         //for IE9-
         return doc.xml;
      } else if (window.XMLSerializer) {
         //for IE9 Mozila Opera Chrome Safari
         return (new XMLSerializer()).serializeToString(doc);
      }
   } catch(err) {
      alert('转换错误,可能参数不是合法的DOM对象');
   }
}
</script>
但是,jQuery也并非万能,没有定义怎样把DOM转换成字符串的跨浏览器解决方案。在使用jQuery之前,需要在HTML文档head元素内引用jQuery库:
<script type="text/javasript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1
/jquery.min.js">
大多数情况下,无须使用jQuery.ajax()方法,除非需要使用一些不常用的选项,以获得更多的灵活性。jQuery提供了几个便捷的Ajax请求方法:
·jQuery.get():使用GET方法执行一个HTTP请求
·jQuery.getJSON():使用GET方法执行一个HTTP请求,获取JSON编码格式的数据
·jQuery.getScript():使用GET方法执行一个HTTP请求,获取一段JavaScript代码,然后执行这段代码
·jQuery.post():使用POST方法执行一个HTTP请求
·.load():执行HTTP请求从远程加载HTML代码甚至代码片段并插入至匹配的元素中

4.HTTP协议:

HTTP是超文本传输协议Hypertext Transfer Protocal,用于从www服务器传输超文本到本地浏览器,最早由Web发明人Berners-Lee制定,目前由W3C维护,有HTTP 1.0和HTTP 1.1两个稳定的版本。HTTP是应用层协议,基于"请求/响应"模式的无状态的协议,建立在TCP协议基础上。

1)HTTP消息的内容:

浏览器和Web服务器之间会通过HTTP在Internet上进行数据的发送和接收,这些数据也被称为HTTP消息(Message)。HTTP消息可以是客户端到服务器的请求消息,也可以是服务器到客户端的响应消息。
请求消息和响应消息都是由开始行、消息头(可选)、空行(只有CRLF的行)、消息正文(可选)组成的。
message = start-line
*message-header
CRLF
[message-body]
对于请求和响应,开始行有所不同。请求消息,开始行就是请求行(Request-Line);对于响应消息,开始行就是状态行(Status-Line)。

2)HTTP请求的内容:

客户端通过发送HTTP请求向服务器请求对资源的访问,这时,HTTP请求由下面的内容组成:
message = Request-Line
*message-header
CRLF
[message-body]
①请求行Request-line:
结构如下:
Method Request-URI HTTP-Version CRLF
示例:GET http://localhost/index.html HTTP/1.1(CRLF)
其中的参数及意义见下表:


参数

意义

Method

表示HTTP请求的方法,例如GET、POST等,需要大写

Request-URI

表示一个统一资源标识符

HTTP-Version

表示请求的HTTP协议版本,一般为HTTP 1.1或者HTTP 1.0

CRLF

表示回车换行

②HTTP请求的方法Method:
常见的HTTP请求的方法就是GET、POST和HEAD,也包括其他的方法。见下表:


方法

意义

GET

通过请求URI得到资源

HEAD

类似于GET,但不返回正文信息,用于检查对象是否存在,以及得到对象的元数据

POST

用于添加新的内容

PUT

用于修改某个内容

DELETE

用于删除某个内容

OPTIONS

询问可以执行哪些方法

TRACE

用于远程诊断服务器

除了这些方法,用户还可以自定义其他方法。

3)HTTP响应的内容:

服务器对客户端请求作出响应,这时,HTTP响应由下面的内容组成:
message = Status-Line
*message-header
CRLF
[message-body]
①状态行Status-Line:
结构如下:
HTTP-Version Status-Code Reason-Phrase CRLF
示例:HTTP/1.1 200 OK(CRLF)
其中的参数及意义见下表:


参数

意义

HTTP-Version

表示服务器HTTP协议的版本,一般为HTTP 1.1或者HTTP 1.0

Status-Code

表示服务器发回的状态代码

Reason-Phrase

表示状态代码的文本描述

CRLF

表示回车换行

②状态代码Status-Code:
状态代码由3位数字组成,表示请求是否被理解或被满足,其中第1个数字定义了响应的类别,后面两位数字没有代表任何具体的分类。
状态代码的第1个数字有5个可选的值。见下表:


参数

意义

1xx

指示信息,表示请求已接收,继续处理

2xx

成功,表示请求已经成功接收,并已经被理解和接受

3xx

重定向,必须采取进一步行动以完成请求

4xx

客户端错误,请求中含有错误语法,或者不能完成

5xx

服务器错误,服务器失败,尽管请求是正确的

③原因短语Reason-Phrase:
原因短语,使用短语简单地说明了状态代码所要表达的意思。见下表:


状态值

状态信息

含义

100

Continue

初始的请求已经接受,客户应当继续发送请求的其余部分

101

Switching Protocols

服务器将遵从客户的请求转换到另外一种协议

200

OK

一切正常,请求响应成功

201

Created

服务器已经创建了文档,Location头给出了它的URL

201

Accepted

已经接受请求,但是处理未完成

203

Non-Authoritative Infomation

文档已经正常返回,但一些应答头可能不正确

204

No Content

没有返回新文档,浏览器继续使用原来的文档

205

Reset Content

没有新内容,但浏览器应该重置它显示的内容,比如强制浏览器清除表单输入内容

206

Partial Content

客户发送了一个带有Range头的GET请求,服务器完成了它

300

Multiple Choices

客户请求的文档可以在多个位置找到,这些位置已经在返回的文档内列出。如果服务器要提出优先选择,则应该在Location应答头指明

301

Moved Permanently

客户请求的文档在其他地方,新的URL在Location头中给出,浏览器应该自动地访问新的URL

302

Moved Temporarily

类似于301,但新的URL应该被视为临时性的替代,而不是永久性的

303

See Other

类似于301/302,不同之处在于,如果原来的请求是POST,Location头指定的重定向目标文档应该通过GET提取

304

Not Modified

客户端有缓冲的文档并发出了一个条件性的请求。服务器告诉客户,原来缓冲的文档还可以继续使用

305

Use Proxy

客户请求的文档应该通过Location头所指明的代理服务器提取

306

Unused

 

307

Temporary Redirect

类似于303,但浏览器只能跟随对GET请求的重定向,不能为POST

400

Bad Request

请求出现语法错误

401

Unauthorized

访问被拒绝,客户试图未经授权访问受密码保护的页面

402

Payment Required

保留有效的ChangeTo头响应

403

Forbidden

资源不可用。服务器理解客户的请求,但拒绝处理它。通常由于服务器上文件或目录的权限设置导致。其下面还有几十种详细类别

404

Not Found

无法找的指定位置的资源

405

Method Not Allowed

请求的方法对指定的资源不适用,用来访问本页面的方法不允许

406

Not Acceptable

指定的资源已经找到,但它的MIME类型和客户在Accept头中所指定的不兼容,客户端浏览器不接受所请求页面的MIME类型

407

Proxy Authentication Required

表示客户必须先经过代理服务器的授权

408

Request Timeout

在服务器许可的等待时间内,客户一直没有发出任何请求

409

Conflict

由于请求和资源的当前状态相冲突,因此请求不成功

410

Gone

所请求的文档已经不再可用,而且服务器不知道应该重定向到哪一个地址

411

Length Required

服务器不能处理请求,除非客户发送一个Content-Length头

412

Precondition Failed

请求头中指定的一些前提条件失败

413

Request Entity Too Large

请求的资源大于服务器允许的大小

414

Request URI Too Long

请求资源的URI长度超出了服务器允许的长度

415

Unsupported Media Type

不支持的媒体类型

416

Requested Range Not Satisfiable

服务器不能满足客户在请求中指定的Range头

417

Expectation Failed

执行失败

500

Internal Server Error

服务器遇到意料不到的情况,不能完成客户的请求,下面有几种详细类别

501

Not Implemented

服务器不支持实现请求所需要的功能,页眉值指定了为实现的配置

502

Bad Gateway

服务器作为网关或者代理时,为了完成请求访问下一个服务器,但该服务器返回了非法的应答

503

Service Unavailable

服务不可用,服务器由于维护或者负载过重未能应答

504

Gateway Timeout

网关超时,由作为代理或网关的服务器使用,表示不能及时地从远程服务器获得应答

505

HTTP Version Not Supported

服务器不支持请求中所指明的HTTP版本

4)HTTP消息报头的内容:

HTTP消息报头包括普通报头(general-header)、请求报头(request-header)、响应报头(response-header)、实体报头(entity-header)。每个报头字段由下面的格式组成:
  名字+":"+空格+值
并且,消息报头字段的名字不区分大小写。
①普通报头general-header:
有少数报头字段既可以应用于请求消息,也可以应用于响应消息,但并不用于被传输的实体,这些报头字段只用于传输的消息。
常用的普通报头有:
Cache-Control
Date
Connection
Pragma
Transfer-Encoding
Upgrade
Via
②请求报头request-header:
请求报头允许客户端向服务器传递该请求的附加信息以及客户端自身的信息,就像是为程序提供附加的参数。
常用的请求报头包括:
Accept
Accept-Charset
Accept-Encoding
Accept-Language
Authorization
From
Host
If-Modified-Since
If-Match
If-None-Match
If-Range
If-Unmodified-Since
Max-Forward
Proxy-Authorization
Range
Referer
User-Agent
③响应报头response-header:
响应报头,允许服务器传递不能放在状态行中的附加响应信息,以及关于服务器的信息和对Request-URI所标识的资源进行下一步访问的信息。
常用的响应报头包括:
Age
Location
Proxy-Authenticate
Public
Retry-After
Server
Vary
Warning
WWW-Authenticate
④实体报头entity-header:
实体由实体报头和实体正文组成。实体正文就是请求消息中的请求正文或者响应消息中的响应正文。实体报头定义了关于实体正文所标识的资源的元数据信息。
常用的实体报头为:
Allow
Content-Encoding
Content-Language
Content-Length
Content-Type
Last-Modified
Expires
除了这些字段,实体报头还可以自定义字段。

5.PHP程序中获取和处理请求报头:

使用PHP内建的函数和全局变量可以获取对HTTP请求中传递的任何消息的访问,当然也可以获取HTTP请求报头中的消息。

1)getallheaders()函数:

getallheaders()函数可以获取HTTP请求报头中的信息。如果Web服务器使用Apache,并且PHP是以模块module方式执行,那么就可以使用函数getallheaders()获得所有HTTP报头信息。语法格式为:
getallheaders();
使用该函数不需要任何参数,返回的是所有HTTP报头信息,并以复合数组形式返回。示例:
<?php
$headers=getallheaders();
while (list($header,$value)=each($headers)) {
echo "<b>$header;</b>$value<br />";
}
?>

2)$_SERVER复合数组:

也可以使用预定义的超全局变量$_SERVER来获取所有的请求报头,这个变量可以用于所有的Web服务器。$_SERVER是一个包含诸如报头信息、路径和script位置的复合数组,见下表:


信息名称

含义

PHP_SELF

当前正在执行脚本script的文件名,与document root相关

argv

传递给该脚本的参数,当调用GET方法时该变量包含请求的数据

argc

包含传递给程序的命令行参数的个数(如果运行在命令行模式)

GATEWAY_INTERFACE

服务器使用的CGI规范的版本

SERVER_NAME

当前运行脚本所在服务器主机的名称,如果是虚拟主机与设定值决定

SERVER_SOFTWARE

服务器标识的字串,在响应请求时的头信息中给出

SERVER_PROTOCOL

请求页面时通信协议的名称和版本,如HTTP/1.0

REQUEST_METHOD

访问页面时请求的方法,如GET、HEAD、POST、PUT

REQUEST_TIME

请求开始时的时间戳

QUERY_STRING

查询的字符串,URL中第一个问号之后的内容

DOCUMENT_ROOT

当前运行脚本所在的文档根目录,在服务器配置文件中定义

HTTP_ACCEPT

当前请求的Accept报头信息的内容

HTTP_ACCEPT_CHARSET

当前请求的Accept-Charset报头信息的内容,如utf-8

HTTP_ACCEPT_ENCODING

当前请求的Accept-Encoding报头信息的内容,如gzip

HTTP_ACCEPT_LANGUAGE

当前请求的Accept-Language报头信息的内容,如en

HTTP_CONNECTION

当前请求的Connection报头信息的内容,如Keep-Alive

HTTP_HOST

当前请求的Host报头信息的内容

HTTP_REFERER

链接到当前页面的前一页面的URL地址,有些可以手工修改此变量

HTTP_USER_AGENT

当前请求的User-Agent报头信息的内容,访问该页面的用户代理信息

HTTPS

如果脚本是通过HTTPS协议被访问,则被设为一个非空的值

REMOTE_ADDR

正在浏览当前页面用户的IP地址,用于记录访问用户的IP

REMOTE_HOST

正在浏览当前页面用户的主机名,反向域名解析基于REMOTE_ADDR

REMOTE_PORT

用户连接到服务器时所使用的端口

SCRIPT_FILENAME

当前使用脚本的绝对路径名

SERVER_ADMIN

APACHE服务器配置文件中的SERVER_ADMIN参数,或虚拟主机的值

SERVER_PORT

服务器所使用的端口,默认80,若使用SSL则为用户设置的HTTP口

SERVER_SIGNATURE

包含服务器版本和虚拟主机名的字符串

PATH_TRANSLATED

当前脚本所在文件系统的基本路径,服务器虚拟到真实路径的映射

SCRIPT_NAME

包含当前脚本的路径,__FILE__包含当前文件的绝对路径和文件名

REQUEST_URI

访问此页面所需的URI,如 /index.html

PHP_AUTH_DIGEST

当作为APACHE模块运行时,被设置为客户端发送的Authorization HTTP头内容

PHP_AUTH_USER

当PHP运行在APACHE或IIS模块方式下,并且正在使用HTTP认证功能,此变量是用户输入的用户名

PHP_AUTH_PW

当PHP运行在APACHE或IIS模块方式下,并且正在使用HTTP认证功能,此变量是用户输入的密码

AUTH_TYPE

当PHP运行在APACHE模块方式下,并且正在使用HTTP认证功能,此变量是认证的类型

数组的实体由服务器创建,所以不能保证所有的Web服务器都能产生所有的信息,可能忽略了一些信息,或者产生了一些未在表中的信息。
使用phpinfo()函数也可以获取相关信息。示例:
http://localhost/myDir/phpinfo.php?var_1=value_1&var_2=value_2
则在返回的信息中可以看到相应的$_SERVER复合数组。
可以用script代码列出所有的内容信息:
<?php
$headers=$_SERVER;
while (list($header,$value)=each($headers)) {
echo "<b>$header;</b>$value<br />";
}
?>

6.对请求作出响应:

当要从服务器传送资料到客户端时,可以直接使用HTML代码,即在处理.php文件时,任何没有包含在<?php ?>或者script元素中的文本都将被简单地返回给浏览器。
如果想动态地向客户端传送数据或者重定向网页,以及设置数据的传送格式时,一般就必须使用一些函数返回HTTP响应报头和正文。

1)返回信息正文给客户端:

PHP内建有很多函数和语言结构,可以将指定的字符串写到当前的HTTP输出,用于消息正文(基本也就是HTML正文)。最常用的便是echo和print。语法格式为:
 echo $arg[,$arg1…$argN];
 print $arg;
这些参数可以是任何数据类型,包括字符串、数字、逻辑值以及对象、数组等,但是对象、数组仅能返回类型标识符。
如果是单个参数,echo可以加上括号,就像一个函数。echo可以指定多个参数,但无返回值,运算速度较快。print有返回值,所以速度较慢,并且仅能有一个参数。

2)返回响应状态行和响应报头给客户端:

使用函数header()可将HTTP响应状态行和报头发送到浏览器,用指定的值添加HTTP报头。语法格式为:
 header($string[,$replace[,$http_response_code]]);
参数$string用来定义HTTP响应状态行和报头;可选参数$replace用来定义是否替换HTTP响应已有的相同状态行和报头,true表示替换,false表示用不同的值发送同一报头的多份副本;可选参数$http_response_code表示强制更改状态码。
①返回状态行:
根据HTTP规范,状态行的结构如下:
 HTTP-Version Status-Code Reason-Phrase CRLF
如下代码发送状态行信息,告诉用户访问未授权:
<?php
header("HTTP/1.0 401 Unauthorized");
?>
另一个常用的状态码是告诉用户未发现请求的文件:
<?php
header("HTTP/1.0 404 Not Found");
?>
②返回响应报头:
下面的代码发送报头要求客户端使用BASIC验证:
<?php
header("WWW-Authenticate: BASIC");
?>
有一些报头不会有图形化的呈现,例如,如果让用户每次都能得到最新的数据,而不是代理服务器或者浏览器缓存的旧数据,就可如下发送报头:
<?php
//首先定义一个旧日期,这里是计算机元年
header("Expires: Thu, 01 Jan 1970 00:00:00 GMT");
//然后定义要访问的文件总是最新修改的
header("Last-Modified: ".gmdate("D,d M Y H:i:s")." GMT");
//处理客户端缓存,HTTP 1.1协议适用
header("Cache-Control: no-store,no-cache,must-revalidate");
header("Cache-Control: post-check=0,pre-check=0",false);
//处理客户端缓存,HTTP 1.0协议适用
header("Pragma: no-cache");
?>
如果想让用户下载一个文件,就可以如下定义:
<?php
//下面将输出一个pdf文件
header("Content-type: application/pdf");
//文件名为download.pdf
header("Content-Disposition: attachment;filename='download.pdf'");
//PDF源文件为original.pdf
readfile('original.pdf');
?>
应该将函数header()放在网页的顶部和<html>标记之前,以确保没有任何内容返回给浏览器。如果在返回给浏览器的内容或者报头后使用header()函数,将会得到一个错误信息。

3)缓存对消息报头的影响:

由于HTTP协议要求所有的报头都必须在内容之前发送,所以必须在任何的输出发送到客户端之前就调用header()函数,但当激活了缓存的情况例外。在php配置文件php.ini中设置:
output_buffering=On;
这时就可以在script中的任何位置调用header()函数,只要在ob_flush()函数之前执行就行,否则将产生一个运行错误。
可以使用函数headers_send()判断报头是否已经送出。语法格式为:
boolean headers_send([$string &$file[,int &$line]]);
如果报头已经送出则函数返回true,否则返回false。如果定义了$file和$line参数,函数就会将PHP源文件名和输出开始的行号放入这两个变量中。

4)重定向:

如果使用下面的语句,将引导用户浏览器重定向到我的网站,而不是将内容发送给客户端:
<?php
header("Location:http://www.dwenzhao.cn/");
exit;
?>
如果浏览器执行重定向,任何在网页中显式设置的响应正文内容都将被忽略,因此在后面使用exit()函数,退出后面代码的执行。
然而,此方法不向客户端发送该网页设置的其他HTTP报头,这将产生一个重定向URL作为链接包含的自动响应正文。实际上,该语句还会发送一个状态行,因此形成的是类如下列报头:
HTTP 1.0 302 Moved Temporarily
Location URL
不过,HTTP重定向有很多种模式,用户可以定义参数$http_response_code改变状态码,从而使用不同的重定向模式。例如:
<?php
header("Location:http://www.dwenzhao.cn/",true,301);
exit;
?>
这时会形成如下的响应:
HTTP 1.0 301 Moved Permanently
Location: http://www.dwenzhao.cn/
还常使用的重定向模式有303和307。

5)设置响应内容的格式和类型:

当Web服务器将文件和内容返回给浏览器时,应该同时告诉浏览器文件中包含的内容的类型,这可以使浏览器能够决定是否它能自己显示文件内容或者必须调用另一个应用程序。例如,如果Web服务器返回Excel表格,则浏览器必须调用Excel程序显示此网页,Web服务器通过将文件的扩展名映射到MIME类型表来识别文件类型。
除此之外,字符集和代码页关系到浏览器能否正确地显示内容,而区域化设置对于内容能否正确地格式化也至关重要。
使用HTTP报头可以定义响应数据内容的这些问题的处理。一般情况下,HTTP报头默认为text/HTML类型:
content-type:text/html
一般网页会将字符集名称附加到报头后面:
content-type:text/html;charset=ISO-LATIN-7
下面的代码演示了content-type属性设置的一些常见值:
header('Content-type:text/plain');
header('Content-type:text/HTML');
header('Content-type:image/JPEG');
header('Content-type:image/GIF');

6)遍历响应报头:

如果使用PHP5,就可以使用headers_list()函数。语法格式为:
array headers_list();
该函数与getallheaders()返回结果相似,也是一个包含所有HTTP报头信息的数组,但是该数组是一个数字索引的简单数组,而getallheaders()返回的是一个复合数组。并且,getallheaders()返回的是请求报头,headers_list()返回的是响应报头。

7.使用网页缓存优化网络程序:

Ob_flush()函数:立即发送缓存区的数据到客户端,不会关闭缓存
Ob_end_flush()函数:立即发送缓存区的数据到客户端,并关闭缓存
Ob_clear()函数:清除缓冲区中的所有输出,不会关闭缓存
Ob_end_clear()函数:清除缓冲区中的所有输出,并关闭缓存
flush()函数:发送位于缓冲区之外的内容,一般与ob_flush()函数配合使用,并紧跟后面
Ob_start()函数在程序中激活缓存。语法格式为:
bool ob_start([callback $output_callback[,int $chuck_size[,bool $erase]]]);
参数$erase是一个逻辑值,设为false时表示不缓存,服务器在处理script的同时将输出发送给客户端;默认值为true,表示除非当前网页的所有PHP script处理完毕或者调用了ob_flush()函数或ob_end_flush()函数,否则服务器不将响应发送给客户端。
如果当前PHP script缓存设为true,但未调用flush()函数,则服务器将使客户端的请求保持一直处于连接(Keep-Alive)。由于服务器不必为每个客户端创建新的连接,从而节省了时间。不过,缓存将在服务器未处理完当前页面的所有script之前阻止在客户端显示响应。对于较长的和较复杂的script,客户端可能要被迫等待很长一段时间才能看到这一页,有可能会感觉到延迟。

Copyright@dwenzhao.cn All Rights Reserved   备案号:粤ICP备15026949号
联系邮箱:dwenzhao@163.com  QQ:1608288659