hash加密全家族

2007/11/17 15:05 ArthurXF
  我们曾经或多或少都会碰到过MD5密码文件校验之类的。知道MD5是一种不可逆的加密算法。其实MD5只是hash(哈希)中的一种运算规则。那么除了MD5还有多少种呢?请看下面:
引用
print_r(hash_algos());
?>
Array
(
   [0] => md4
   [1] => md5
   [2] => sha1
   [3] => sha256
   [4] => sha384
   [5] => sha512
   [6] => ripemd128
   [7] => ripemd160
   [8] => whirlpool
   [9] => tiger128,3
   [10] => tiger160,3
   [11] => tiger192,3
   [12] => tiger128,4
   [13] => tiger160,4
   [14] => tiger192,4
   [15] => snefru
   [16] => gost
   [17] => adler32
   [18] => crc32
   [19] => crc32b
   [20] => haval128,3
   [21] => haval160,3
   [22] => haval192,3
   [23] => haval224,3
   [24] => haval256,3
   [25] => haval128,4
   [26] => haval160,4
   [27] => haval192,4
   [28] => haval224,4
   [29] => haval256,4
   [30] => haval128,5
   [31] => haval160,5
   [32] => haval192,5
   [33] => haval224,5
   [34] => haval256,5
)


哇!原来hash的运算规则有这么多啊,有好多都是我们所不熟悉的,那么当我们看到一段不规则的字符串的时候,我们如何推断大概是用哪种加密算法生成的呢?请看我们的例子:
引用
我们对http://www.bizeway.net/加密,结果如下:
md2 = 6052a4afb1c91673a19511d87ca7bf9c
md4 = a4b0885c2b84b05320e3f9ac5f16d888
md5 = 5e886a15279d0b021909736d0c7e4eb5
sha1 = b3ef5fc0b12c90353a7355af157e8b5120194516
sha256 = b959552cc7fab5ed47550ba7c0890585c751d78e7a3f6b6866589a7647e4001b
sha384 = 1b0a29f9859d5a7979c39d19df61ed62670b40c6f751f69b9efac9ced84646d234a2ee1601de13db79823d0f8be04c24
sha512 = 0e2ada52b6955ae9b70b1273bfedc6a8974a3a573cd3dee6cf60b9c97de4c78906ed2deb1a291f147ebe0f4bf192680b1a3bef1e9d72f9dca5fecc7c55dd5fdd
ripemd128 = 1c37bca1b2c3a9cd315336b11da1cc51
ripemd160 = 561c00de12c091d4c213baa861c7021474cedae1
ripemd256 = 34dd5a7b2b5cf633c67964f6a2f36266fe24a3b24f9ba4198f09ec839f241181
ripemd320 = ae7bf6f8d0dfcb8072c2f7f7afbecea397570130fa605bb4ee29d65a4049d5a6d00e030938ad2d0c
whirlpool = 8144f3cb8708ca83b1a14438faab52a4b3857a8793ead44c3accacc127b9615f60365dc146522cbda39298fc299a60524eb5e2779f4aa23ed65b156a2b1f1009
tiger128,3 = 982500b72f18c6390b739d0c7f26010b
tiger160,3 = 982500b72f18c6390b739d0c7f26010b839bbed1
tiger192,3 = 982500b72f18c6390b739d0c7f26010b839bbed1a2cb6f6b
tiger128,4 = 3d08e277ad45ea8954631975e30f5857
tiger160,4 = 3d08e277ad45ea8954631975e30f58576cf28c89
tiger192,4 = 3d08e277ad45ea8954631975e30f58576cf28c89eb4de64a
snefru = 271c5f57081c06887292f8e7d852cc1a9b76bc1948fcb31ed748a76650b8ac61
gost = 7344f382e8af17c61e1cd6998d6ad636960f8bcaeeb5c8994130811cce082627
adler32 = 8b082c67
crc32 = f2a81a53
crc32b = ba25f4f1
haval128,3 = d82c54644cca5c6c9b523e8a58089165
haval160,3 = a56db9796f5e54618c3cf8e74719038e525473df
haval192,3 = d56cc89a444810f8c36475a60c8170ced52692a27f9deffb
haval224,3 = fa2759e6289d1b4231df611af6f00a18338964c5e0100aa15975fc02
haval256,3 = 1ec91a5cb89170eb7c185105802850f97a4cf60aa7a3511a8e37a5db804e9917
haval128,4 = aac659a7e7e8f8f5262803d9b49233c4
haval160,4 = e202b7ddeef36e14c5bf8e2e021af865f82c7710
haval192,4 = c7d0dae89617abcc4880e835898de662e22c372fb364d1c4
haval224,4 = 30d8772a3ff47cbc616a58711c4de4555aa04791141f3859d74c5150
haval256,4 = 7748ebecc45adff32b42608f43775fe0803abc908793061cb05923f7d356d303
haval128,5 = 7cd16ab3dd2c05ac2c8c61efd63ea3cb
haval160,5 = 83d38a838eabd27582e423ce31767abc75b4292b
haval192,5 = 1298d602d4761d895f664baa74392b1f544ce1ead2dcc3ad
haval224,5 = a306fe5b1947c39989a23c578f066625d78e0f8a4bd99cbb837f6c40
haval256,5 = a4256c1f4415376340f3ac48e0c26ce9d109297f034392c0341863f5c514eb94

希望上面的资料能够给大家一些帮助
Tags:

php4和php5区别

2007/10/02 09:12 ArthurXF
PHP5 中的对象已经进行了较系统、较全面的调整,现在的样子可能看起来会有些类似于 Java。本小节着重讲述 PHP5 中新的对象模式,并举了一些较简易的例子来说明。就让本节成为你的 PHP5 之旅的一个新起点吧。:)

* 构造函数和析构函数
* 对象的引用
* 对象的克隆
* 对象中的私有、公共及受保护模式
* 接口 (Interfaces)
* 抽象类
* __call
* __set 和 __get
* 静态成员


构造函数和析构函数

在 PHP4 中,当函数与对象同名时,这个函数将成为该对象的构造函数,并且在 PHP4 中没有析构函数的概念。
在 PHP5 中,构造函数被统一命名为 __construct,并且引入了析构函数的概念,被统一命名为 __destruct。

例一:构造函数和析构函数

class foo {
var $x;
function __construct($x) {
$this->x = $x;
}
function display() {
print($this->x);
}
function __destruct() {
print("bye bye");
}
}
$o1 = new foo(4);
$o1->display();
?>
在上面的例子中,当你终止调用 foo 类的时候,其析构函数将会被调用,上例中会输出 “bye bye”。


对象的引用

众所周知,在PHP4 中,传递变量给一个函数或方法,实际是把这个变量做了一次复制,也就意味着你传给函数或方法的是这个变量的一个副本,除非你使用了引用符号 “&” 来声明是要做一个引用,而不是一个 Copy。在 PHP5 中,对象总是以引用的形式存在的,对象中的赋值操作同样也都是一个引用操作。

例二:对象的引用


class foo {
var $x;
function setX($x) {
$this->x = $x;
}
function getX() {
return $this->x;
}
}
$o1 = new foo;
$o1->setX(4);
$o2 = $o1;
$o1->setX(5);
if($o1->getX() == $o2->getX()) print("Oh my god!");
?>

对象的克隆

如上所述,当一个对象始终以引用的形式来被调用时,如果我想得到该对象的一个副本,该怎么办呢?PHP5 提供了一个新的功能,就是对象的克隆,语法为 __clone。

例三:对象的克隆
class foo {
var $x;
function setX($x) {
$this->x = $x;
}
function getX() {
return $this->x;
}
}
$o1 = new foo;
$o1->setX(4);
$o2 = $o1->__clone();
$o1->setX(5); if($o1->getX() != $o2->getX()) print("Copies are independant");
?>
对象克隆的方法在其它很多应用程序语言中都是存在的,所以你不必担心它的稳定性。:)


对象中的私有、公共及保护模式

PHP4 中,一个对象的所有方法和变量都是公共的,这意味着你可以在一个对象的外部操作其中的任意一个变量和方法。PHP5 引入了三种新的用来控制这种存取权限的模式,它们是:公共的(Public)、受保护的(Protected)及私有的(Private)。

公共模式(Public):允许在对象外部进行操作控制。
私有模式(Private):只允许本对象内的方法对其进行操作控制。
受保护模式(Protected):允许本对象及其父对象对其进行操作控制。
例四: 对象中的私有、公共及受保护模式

class foo {
private $x;
public function public_foo() {
print("I'm public");
}
protected function protected_foo() {
$this->private_foo(); //Ok because we are in the same class we can call private methods
print("I'm protected");
}
private function private_foo() {
$this->x = 3;
print("I'm private");
}
}
class foo2 extends foo {
public function display() {
$this->protected_foo();
$this->public_foo();
// $this->private_foo(); // Invalid! the function is private in the base class
}
} $x = new foo();
$x->public_foo();
//$x->protected_foo(); //Invalid cannot call protected methods outside the class and derived classes
//$x->private_foo(); //Invalid private methods can only be used inside the class $x2 = new foo2();
$x2->display();
?>
提示:对象中的变量总是以私有形式存在的,直接操作一个对象中的变量不是一个好的面向对象编程的习惯,更好的办法是把你想要的变量交给一个对象的方法去处理。


接口 (Interfaces)

众所周知,PHP4 中的对象支持继承,要使一个对象成为另一个对象的派生类,你需要使用类似 “class foo extends parent” 的代码来控制。 PHP4 和 PHP5 中,一个对象都仅能继承一次,多重继承是不被支持的。不过,在 PHP5 中产生了一个新的名词:接口,接口是一个没有具体处理代码的特殊对象,它仅仅定义了一些方法的名称及参数,此后的对象就可以方便的使用 'implement' 关键字把需要的接口整合起来,然后再加入具体的执行代码。

例五:接口

interface displayable {
function display();
}
interface printable {
function doprint();
}

class foo implements displayable,printable {
function display() {
// code
} function doprint() {
// code
}
}
?>
这对提高代码的可读性及通俗性有很大的帮助,通过上面的例子可以看到,对象 foo 包含了 displayable 和 printable 两个接口,这时我们就可以清楚的知道,对象 foo 一定会有一个 display() 方法和一个 print() 方法,只需要去了解接口部分,你就可以轻易的操作该对象而不必去关心对象的内部是如何运作的。

抽象类

抽象类不能被实例化。
抽象类与其它类一样,允许定义变量及方法。
抽象类同样可以定义一个抽象的方法,抽象类的方法不会被执行,不过将有可能会在其派生类中执行。

例六:抽象类

abstract class foo {
protected $x;
abstract function display();
function setX($x) {
$this->x = $x;
}
}
class foo2 extends foo {
function display() {
// Code
}
}
?>

__call

PHP5 的对象新增了一个专用方法 __call(),这个方法用来监视一个对象中的其它方法。如果你试着调用一个对象中不存在的方法,__call 方法将会被自动调用。

例七:__call

class foo {
function __call($name,$arguments) {
print("Did you call me? I'm $name!");
}
} $x = new foo();
$x->doStuff();
$x->fancy_stuff();
?>
这个特殊的方法可以被用来实现“过载(overloading)”的动作,这样你就可以检查你的参数并且通过调用一个私有的方法来传递参数。

例八:使用 __call 实现“过载”动作

class Magic {
function __call($name,$arguments) {
if($name=='foo') {
if(is_int($arguments[0])) $this->foo_for_int($arguments[0]);
if(is_string($arguments[0])) $this->foo_for_string($arguments[0]);
}
} private function foo_for_int($x) {
print("oh an int!");
} private function foo_for_string($x) {
print("oh a string!");
}
} $x = new Magic();
$x->foo(3);
$x->foo("3");
?>

__set 和 __get

这是一个很棒的方法,__set 和 __get 方法可以用来捕获一个对象中不存在的变量和方法。

例九: __set 和 __get

class foo {
function __set($name,$val) {
print("Hello, you tried to put $val in $name");
}
function __get($name) {
print("Hey you asked for $name");
}
}
$x = new foo();
$x->bar = 3;
print($x->winky_winky);
?>

类型指示

在 PHP5 中,你可以在对象的方法中指明其参数必须为另一个对象的实例。

例十:类型指示

class foo {
// code ...
}
class bar {
public function process_a_foo(foo $foo) {
// Some code
}
}
$b = new bar();
$f = new foo();
$b->process_a_foo($f);
?>
可以看出,我们可以显性的在参数前指明一个对象的名称,PHP5 会识别出这个参数将会要是一个对象实例。

静态成员

静态成员和静态方法在面象对象编程的术语中被称作 “对象方法(class methods)” 和 “对象变量(class variables)”。
“对象方法” 在一个对象没有实例化前允许被调用。同样,“对象变量” 在一个对象没有实例化前可以被独立操作控制(不需要用一个对象的方法来控制)。

例十一:对象方法和对象变量

class calculator {
static public $pi = 3.14151692;
static public function add($x,$y) {
return $x + $y;
}
}
$s = calculator::$pi;
$result = calculator::add(3,7);
print("$result");
?>

异常处理

异常处理是公认的处理程序错误的理想方法,在 Java 及 C++ 中都有这个概念,我们欣喜的看到,在 PHP5 已经加入了这方面的应用。你可以尝试使用 “try” 和 “catch” 来控制程序的错误。

例十二:异常处理

class foo {
function divide($x,$y) {
if($y==0) throw new Exception("cannot divide by zero");
return $x/$y;
}
}
$x = new foo();
try {
$x->divide(3,0);
} catch (Exception $e) {
echo $e->getMessage();
echo "n
n";
// Some catastrophic measure here
}
?>
上例中,我们使用了 “try” 来执行花括号中的语句,当有错误发生的时候,代码会把错误交给 “catch” 子句来处理,在 “catch” 子句中,你需要指明要把错误交给某个对象处理,这样做可以使代码结构看起来更清晰,因为现在我们可以把所有的错误信息交给一个对象来处理。


自定义错误处理

你可以很方便的用自定义的处理错误的代码来控制你的程序中的意外。你仅仅需要从异常类中派生出一个自己的错误控制类,在你自己的错误控制类中,你需要有一个构造函数和一个 getMessage 方法,以下是一个例子。

例十三:自定义错误处理

class WeirdProblem extends Exception {
private $data;
function WeirdProblem($data) {
parent::exception();
$this->data = $data;
}
function getMessage() {
return $this->data . " caused a weird exception!";
}
}
?>
现在我们可以使用 “throw new WeirdProblem($foo)” 来抛出一个错误句柄,如果错误在 “try” 的代码块中发生,PHP5 会自动把错误交给 “catch” 部分来处理。


名称空间

名称空间对类的分组或函数分组很有用。它可以把一些相关的类或函数给组合到一起,方便以后调用。

例十四:名称空间

namespace Math {
class Complex {
//...code...
function __construct() {
print("hey");
}
}
} $m = new Math::Complex();
?>
注意你需要在何种情况下使用名称空间,在实际运用中,你可能会需要声明两个或多个名称一样的对象来做不同的事情,那么你就可以把他们分别放到不同的名称空间中去(但接口是要相同的)。

Tags: ,

PHP 程序加速探索

2007/08/11 19:17 ArthurXF
- (一)简介
- (二)是否需要加速?
- (三)如何加速?
   -<1> 测试
       ◆ 服务器负载测试 ApacheBench
       ◆ 脚本执行速度测试 PEAR:: Benchmark
   -<2> 加速
       ◆ 代码优化
      ◆ 压缩输出 Gzip
      ◆ 内容缓存输出 PEAR Content cache
      ◆ 函数缓存输出 PEAR Function cache
      ◆ 加速工具软件 APC、Turck MMCache、PHPA、Zend Performance Suite
- (四)总结

(一)简介

  本文尝试对PHP程序加速的各个方面进行探索,包括必要性以及从不同角度采取的具体措施。希望有助于读者了解PHP程序加速,并应用于实际。

(二)是否需要加速?

  这个问题听起来有点愚蠢。在这个时代,很少有人会怀疑时间是最宝贵的财富,尤其是在商业市场上。程序执行越快,用户就节约越多的时间,这样你的程序就可以用更少的时间和服务器资源为用户服务,从而产生更多效益。
我想对于大部份人(包括我自己)来说,很多WEB项目都是在很紧张的时间里完成的,通常没有经过缜密的思考和严格的测试。当开始一个新的WEB项目。很多人都在构建那种“快而乱”的应用,缺乏必要的时间来调整和改良代码,这时优化和加速就是我们必须采取的措施。
  然而需要特别指出的是,并不是所有程序都需要加速。
  优化已完成的代码是很浪费时间的,最好的方法是在写代码的时候就注意到效率,然后完成项目后只优化确实需要优化的那部份。一般一个程序只会有少数几个影响速度的瓶颈,将它们找出来并解决掉,程序就可以很好地运行。另外,当遇到执行效率低下的情况,首先要用大局的眼光来找出影响效率的主要因素,而不要拘泥于细节—例如数据量过大,服务器带宽不够,或硬件配置过低,在这样的情况下,优化代码于事无补。
  另外,在没有发现程序有明显的执行缓慢的迹象时,就不要太吹毛求疵,为了改进一些非常细节的代码而浪费时间。用这些时间,你可以完成另一个项目或为原来的项目完成一个扩展功能。当然你可以笑话我不够负责,没有把工作做得尽善尽好,我也可以说你是完美主义者:-)  
  综上,在你决定为你的PHP程序提速之前,问问自己是否有必要。

(三)如何加速?

要回答“如何加速”这个问题前,需要先回答以下两个小问题:
你的程序慢在哪一部份?
PHP可以从哪几个方面考虑加速?
  第一个小问题显然我无法给你答案,但我建议你用“测试脚本执行速度”的方法来解决。只有找出限制速度的瓶颈,才能考虑如何去解决。
  第二个小问题我大概的答案是:代码优化,压缩输出,内容缓存输出,函数缓存输出,加速/缓存工具软件。如果你知道更多请告诉我:-)
  下面我们来详细地研究一下这几个方面的相关技术。当然实际上每个方面都有无数的细节可以讨论,下面的内容难免会有片面的地方,欢迎补充。

<1> 测试
◆ 服务器负载测试


  服务器负载太大而影响程序效率也是很常见的,我们需要对此进行测试。这里我以目前最常用的Apache服务器为例。
  Apache服务器自带有一个叫AB(ApacheBench)的工具,在bin目录下。使用这个轻巧的工具我们可以对服务器进行负载测试,看看在重负荷之下服务器的表现如何。ApacheBench 可以针对某个特定的 URL 仿真出连续的联机请求,同时还可以仿真出同时间点数个相同的联机请求,因此利用 ApacheBench 可帮助我们在网站开发期间仿真实际上线可能的情况,利用仿真出来的数据作为调整服务器设定或程序的依据。
  在命令行下输出:

./ab -n number_of_total_requests \
-c number_of_simultaneous_requests \
http://your_web_server/your_php_app.php

例如:

./ab -n 1000 -c 50 http://www.domain.com/myapp.php

  AB将同时向http://www.domain.com/myapp.php发出50个并发请求,共发出1000次。
  测试结果将可能是这样的:

Server Software: Apache/2.0.16
Server Hostname: localhost
Server Port: 80
Document Path: /myapp.php
Document Length: 1311 bytes
Concurrency Level: 50
Time taken for tests: 8.794 seconds
Complete requests: 1000
Failed requests: 0
Total transferred: 1754000 bytes
HTML transferred: 1311000 bytes
Requests per second: 113.71
Transfer rate: 199.45 kb/s received
Connection Times (ms)
min avg max
Connect: 0 0 5
Processing: 111 427 550
Total: 111 427 555

  myapp.php每秒钟可以处理的请求数为113.71个。将请求数增加,看看服务器能否处理更大的压力。你也需要调节Apache的MaxClients, ThreadsPerChild, MaxThreadsPerChild 等参数,基于你的 httpd.conf 中的 MPM 模块选择。
  如果你想得到更详细的信息,请到www.apache.org上查阅一些更深入的文档,包括模块和第三方的提高效率的工具。修改httpd.conf后,要重启Apache服务器,然后再用AB测试。你会看到每秒请求数增加或减少。
  记下每次的参数,最后选择最佳效率的那种配置。
  要指出的是,除了AB,还有许多优秀的服务器性能测试软件。另外,如果你的服务器不是 Apache,请自行寻找测试方法。

◆ 脚本执行速度测试

  前面有提到,只有找到影响速度的代码,我们才有可能进行优化。PEAR的benchmark包中的Benchmark_Timer类和Benchmark_Iterate类,可以用来很方便地测试脚本执行的速度。(关于PEAR的安装与配置请自行查看相关资料)
首先用Benchmark_Iterate类来测试程序中某个函数或类的某个方法的执行时间。

benchmark1.php


require_once('Benchmark/Iterate.php');
$benchmark = new Benchmark_Iterate();

$benchmark->run(10, 'myFunction','test');
$result = $benchmark->get();
echo "

"; print_r($result); echo "
";
exit;

function myFunction($var) {
   // do something
   echo 'Hello ';
}

?>

  建立benchmark Iterate对象$benchmark,这个对象用来执行myFunction函数10次。
  $argument变量每次都传递给myFunction. 多次运行的分析结果存入$result,然后用benchmark对象的get()方法来获取。这个结果用print_r()输出到屏幕。通常会输出这样的结果:
  Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello
Array(
   [1] => 0.000427    [2] => 0.000079    [3] => 0.000072    [4] => 0.000071    [5] => 0.000076    [6] => 0.000070    [7] => 0.000073    [8] => 0.000070    [9] => 0.000074    [10] => 0.000072    [mean] => 0.000108    [iterations] => 10)
  myFunction的每次执行,benchmark对象都会跟踪执行时间。并且会计算平均的执行时间([mean]那一行)。通过多次运行目标函数,你可以得到该函数的平均运行时间。
  在实际测试中,函数的次数应当至少1000次左右,这样可以得到较客观的结果。

  现在我们看看另一个测试脚本运行时间的方法--使用Benchmark_Timer类来测试一段代码执行所消耗的时间及这一段代码中每次调用与下一次调用间的时间。

benchmark2.php

require_once 'Benchmark/Timer.php';
$timer = new Benchmark_Timer();
$timer->start();
$timer->setMarker('start_myFunction');

for($i=0; $i<10; $i++){
   myFunction($argument);
}
$timer->setMarker('end_myFunction');
$timer->stop();
$profiling = $timer->getProfiling();

echo '
Time elapsed: ' .
$timer->timeElapsed('start_myFunction','end_myFunction') .'
';
echo '
'; print_r($profiling); echo '
';
exit;

function myFunction($var) {
   static $counter = 0;
   // do something
   echo $counter++ . ' ';
}
?>


  首先,建立一个benchmark timer对象$timer。然后调用start()方法,表示开始计时。 SetMaker()方法用来标记要测试的代码段。MyFunction()函数在循环中被调用,表示一段要执行的代码(当然实际中不会这么简单)。然后再用$timer对象的setMarker()方法标记程序执行终点。分析信息用getProfiling()来获取。在两个标记间程序执行消耗的时间用timeElapsed()方法计算出来(就像例子中的循环)。最后,用print_r()输出信息到屏幕:
Array(    [0] => Array        (            [name] => Start            [time] => 1085730111.27175200            [diff] => -            [total] => 1085730111.271752        )     [1] => Array        (            [name] => start_myFunction            [time] => 1085730111.27203800            [diff] => 0.000286            [total] => 1085730111.272038        )     [2] => Array        (            [name] => end_myFunction            [time] => 1085730111.27263200            [diff] => 0.000594            [total] => 1085730111.272632        )     [3] => Array        (            [name] => Stop            [time] => 1085730111.27271800            [diff] => 0.000086            [total] => 1085730111.272718        ))
0 1 2 3 4 5 6 7 8 9
Time elapsed: 0.000594

  通过这种方法,你可以在代码中设置大量时间段标记,获取每段代码执行时消耗的时间,很容易可以看出到底是哪一部份的代码影响了整个程序的运行效率。然后开始着手对这部份代码进行改进。
  用以上两种方法,你可以找出代码中最影响速度的部份代码。另外还可以用来对优化后的代码进行测试,看看到底执行速度提高了多少。通过测试->优化->测试->优化 …这样不断循环,你可以最终确定提供最佳效率的代码。

<2> 加速

◆ 代码优化
  掌握了PEAR::BenchMark,现在你已经知道如何测试你的代码,知道如何判断你的代码是快是慢,是哪一部份比较慢。那么接下来我要说的就是如何消灭或优化那部份慢的代码。
这一点上我个人最主要的经验只有两点,一是消除错误的或低效的循环;二是优化数据库查询语句。其实还存在一些其它的优化细节,比如“str_replace比ereg_replace快”、“echo比print快”等等。这些我暂时都放在一边,稍后我会提到用缓存来对付过于频繁的IO。
下面我们将三个功能相同,但程序写法不同的函数的效率(消耗的时间)进行对比。

badloops.php

require_once('Benchmark/Iterate.php');
define('MAX_RUN',100);
$data = array(1, 2, 3, 4, 5);

doBenchmark('v1', $data);
doBenchmark('v2', $data);
doBenchmark('v3', $data);
function doBenchmark($functionName = null, $arr = null)
{
   reset($arr);
   $benchmark = new Benchmark_Iterate;
   $benchmark->run(MAX_RUN, $functionName, $arr);
   $result = $benchmark->get();
   echo '
';
   printf("%s ran %d times where average exec time %.5f ms",$functionName,$result['iterations'],$result['mean'] * 1000);
}

function v1($myArray = null) {
   // 效率很差的循环
   for ($i =0; $i < sizeof($myArray); $i++)
   {
       echo ' ';
   }
}

function v2($myArray = null) {
   // 效率略有提高
   $max = sizeof($myArray);
   for ($i =0; $i < $max ; $i++)
   {
       echo ' ';
   }
}

function v3($myArray = null){
   //最佳效率
   echo " ";
}
?>

  程序输出的结果大概是这样的:

v1 ran 100 times where average exec time 0.18400 ms
v2 ran 100 times where average exec time 0.15500 ms
v3 ran 100 times where average exec time 0.09100 ms

  可以看到,函数的执行时间变少,效率上升。
  函数v1有个很明显的错误,每一次循环的时间,都需要调用sizeof()函数来计算。函数v2则在循环外把$myArray数组的元素个数存到$max变量中,避免了每次循环都要计算数组的元素个数,所以效率提高了。函数v3的效率最高,利用了现成的函数,避免循环。
  这个例子只是给你一个感性的认识,明白什么是相对高效的代码。在实际开发中,我相信会有很多人会迷迷糊糊地写出很多低效率的代码。要把代码写得精炼而高效,恐怕需要时间去锤炼:-) 但这是另一个话题了,我们略过不谈。
  数据库应用基本上每个PHP程序都会用到,在实际开发中我发现最影响整个系统效率的就是数据库这部份。至于数据库的优化和数据查询语句的优化,在此限于篇幅不详细讨论。你可以参看这两篇文章:
http://www.phpe.net/articles/340.shtml
http://www.phpe.net/articles/323.shtml
  及这篇讨论:
http://club.phpe.net/index.php?s=&act=ST&f=15&t=4783&st=0(前面几篇贴子总结不错),主要是针对MySQL的。

◆压缩输出 gzip

  利用Apache中的mod_gzip模块,我们可以利用gzip的压缩算法来对Apache服务器发布的网页内容进行压缩后再传输到客户端的浏览器。如果是纯文本的内容,效果非常明显,大约可以压缩到原来的30%-40%,使用户的浏览速度大大加快。
  Gzip需要客户端浏览器支持,目前大部份浏览器都支持gzip,如IE,Netscape,Mozilla等,所以这种方法值得一试。我们可以利用PHP中的预定义变量$_SERVER[‘HTTP_ACCEPT_ENCODING’]来判断客户端浏览器是否支持gzip。

gzip1.php


if(ereg('gzip',$_SERVER['HTTP_ACCEPT_ENCODING'])) {
   //浏览器支持
} else {
   //浏览器不支持,输出其它内容
}
?>

  接下来我们对上面这个PHP程序进行扩展,使用ob_start(ob_gzhandler)来将网页内容压缩,存入缓冲并发送给支持gzip的浏览器,浏览器会自动将压缩后的内容解压,显示。

gzip2.php

define('MAX',100);

if(ereg('gzip',$_SERVER['HTTP_ACCEPT_ENCODING']))
{
   //浏览器支持gzip,将内容压缩并缓冲输出
   ob_start("ob_gzhandler");
   $output = '';

   for($i=0;$i<=MAX;$i++)
   {
       $output .= "This is line $i
";
   }
   echo "浏览器支持gzip压缩输出
";
   echo $output;
}
else
{
   //浏览器不支持,直接输出
   for($i=0;$i<=MAX;$i++)
   {
       $output .= "This is line $i
";
   }

   echo "浏览器不支持gzip压缩输出
";
   echo $output;
}
?>


  使用gzip压缩生成的网页的HTTP头信息与一般的网页相比中会多出这样的信息:

Content-Encoding: gzip
Content-Length: 270

  如果你想得到更详细的信息,请参看mod_gzip项目主页:
http://sourceforge.net/projects/mod-gzip/

  类似地,我们也可以利用mod_deflate,压缩率比mod_gzip略低一些。调用zip函数需要耗用服务器内存,所以要慎用,视需求而定。

◆ 内容缓存输出 PEAR cache

  接下来我们开始探索更常用的缓存技术,这也是本文的重点部份。首先我们使用PEAR中的cache包。PEAR可以将内容缓存于文件,数据库或者内存中,我们以文件为例。
  下面是一个没有使用缓存的PHP小程序:

pear_content_cache1.php

echo "这是内容。

";
echo "当前时间是" . date('M-d-Y H:i:s A', time()) . "
";
?>

  上面这个程序非常简单,现在我们为其加上缓存。

pear_content_cache2.php

require_once 'Cache/Output.php';

//设置缓存目录,必须是可写的
$cacheDir = './pear_cache';
$cache = new Cache_Output('file',array('cache_dir' => $cacheDir));

//如果nocache变量为空,使用缓存中的内容
//如果想获得最新的内容,就要赋值给nocache变量
if (empty($_REQUEST['nocache']))
{
   // 建立一个独一的cache标识
   // 请求+Cookie信息
   $cache_id = $cache->generateID(array('url' => $_REQUEST,'post' =>$_POST,'cookies' => $HTTP_COOKIE_VARS));
}
else
{
   //想获得最新的内容,ID为空
   $cache_id = null;
}


//看cache ID对应的缓存内容是否可用
if ($content = $cache->start($cache_id))
{
   //缓存已存在,直接输出,并结束脚本
   echo $content;
   exit();
}

// 缓存中不存在该内容,生成新内容并写入缓存
echo "这是内容。

";
echo "当前时间是" . date('M-d-Y H:i:s A', time()) . "
";
// 把内容写入缓存
echo $cache->end();
?>

  分别刷新这两个文件,你会发现pear_content_cache1.php中的“当前时间是”这一行中的时间是随着刷新而变化的,而pear_content_cache2.php中的这一行则不变。这是由于pear_content_cache2.php使用了缓存,将用户请求的内容存入静态文件中。当用户再次请求时,它直接从文件中输出,而不需要用程序动态生成内容。
  对于pear_content_cache2.php,如果用户想要读取最新的信息,而不是缓存中成旧的信息。那么可以用http://…/pear_content_cache2.php?nocache=1 来访问,这将禁用缓存功能。刷新一下看看,你将发现时间会随之变化。
  总结一下PEAR内容缓存类的使用:
  1.包含PEAR包 要注意设对路径。
  2.包含Output.php中的cache类
require_once 'Cache/Output.php';
  3.设置缓存目录
$cacheDir = './pear_cache';
  确认这个目录是可写的。Cache数据将会写入这个目录的子目录中。
  4.建立一个输出缓存对象
$cache = new Cache_Output('file',array('cache_dir' => $cacheDir));
  第一个参数表示我们使用基于“文件”方式的缓存,第二个参数是一个与缓存目录相关联的数组。
  5.产生一个唯一的cache ID
$cache_id = $cache->generateID(array('url' => $_REQUEST,'post' =>$_POST,'cookies' => $HTTP_COOKIE_VARS));
  这里$cache对象的generateID()方法通过提供一个信息数组(URL, HTTP POST data, 和 HTTP cookie)来独一无二地标识这个请求,与其它请求区分开来。
  6.增加一个逻辑判断语句看是否对应于cacheID的缓存数据是否已经存在,如果存在,获取数据并结束脚本。
if ($content = $cache->start($cache_id))
{   echo $content;
   exit();
}
  7. 将产生内容的代码放在以上逻辑语句之后,并结束使用cache对象。
echo $cache->end();

◆ 函数缓存输出 PEAR cache

  PEAR除了可以对输出的内容进行缓存处理外,还可以将对某个函数的调用结果缓存起来。这是个很有趣的功能,如果你的程序要频繁使用到某个函数,而且调用的结果相同的话,我建议你不妨试试,特别是当这个函数运行起来比较慢的时候。

  下面我们实现对一个执行起来很慢的函数slowFunction()的缓冲调用。

require_once 'Cache/Function.php';


$cacheDir = './pear_cache/';
$cache = new Cache_Function('file',array('cache_dir' => $cacheDir));
$arr = array('苹果', '梨','西瓜');
$cache->call('slowFunction', $arr);
echo '
';

$arr = array('苹果', '梨','西瓜');
slowFunction($arr);

function slowFunction($arr = null)
{
   echo "一个执行起来很慢的函数 :(
";
   echo "当前时间是 " . date('M-d-Y H:i:s A', time()) . '
';
   foreach ($arr as $fruit)
   {
       echo "我吃了一个 $fruit
";
   }
}
?>

      以下是示例的脚本执行结果:
一个执行起来很慢的函数 :(
当前时间是 Jul-28-2004 17:15:57 PM
我吃了一个 苹果
我吃了一个 梨
我吃了一个 西瓜

一个执行起来很慢的函数 :(
当前时间是 Jul-28-2004 17:17:55 PM
我吃了一个 苹果
我吃了一个 梨
我吃了一个 西瓜
  代码中,Cache/Function.php类用来执行函数缓冲功能。$cache变量是一个Cache_Function对象,使用基于文件的函数缓存,存入$cacheDir目录。要缓存一个函数调,Cache_Function对象$cache的call()方法要像这样使用:$cache->call(‘slowFunction’, $arr);
  这里,slowFunction()函数被调用,参数为一个数组$arr,这个函数被缓存在$cacheDir目录下的一个文件里。任何在此之后的对这个函数的调用,将会由$cache->call()返回该函数执行的结果。
  函数缓存和使用方法和内容缓存很相似,不再多说,具体请查看PEAR手册。

  以上我们都是利用优化代码的方法对程序进行提速,接着我们要关注一下PHP加速的另一个领域—缓存工具软件。这类软件都是从优化PHP运行环境来提速的,不需要改变任何代码。我们可以大概地将它们称为“执行码优化/缓存工具”,你可以理解为它们用来实现比较底层的优化/缓存。

  以下列出目前比较常用的此类工具,具体哪种效果最好,请用自己的服务器环境测试:
(一)APC Alternative PHP Cache
http://apc.communityconnect.com/
  APC运行于Linux和FreeBSD,你需要自己编译安装。按照其开发人员的说法,在他们的测试环境下可以提高脚本速度50%-400%。并且APC是个开源项目,已经加入了PHP的PECL库,很值得一试。
(二)Turck MMCache
http://turck-mmcache.sourceforge.net/
  Turck MMCache似乎是此类软件中目前最受欢迎的一种,它开放源代码,完全免费。它将PHP代码预编译并缓存起来,同时也对PHP运行环境进行一定优化。按照其官方文档的说法,MMCache可以明显地减轻服务器的负载,并提高脚本执行速度1-10倍。
  MMCache与另一个知名的加速软件Zend Optimizer兼容,但注意必需先安装MMCache(php.ini中设置)。除了加快PHP程序的速度,MMCache还可以将PHP代码加密。
  Turck MMCache同时支持Linux和Win32平台。
(三)PHPA  the PHP Accelerator
http://www.php-accelerator/
  PHPA又是另一个流行的PHP加速软件。在其官方网站上有分别使用PHPA与APC、Zend Cache的PHP脚本执行测试对比,其表现略优于APC,略逊于Zend Cache。
   PHPA支持Linux, FreeBSD, OpenBSD, BSDi和Solaris系统.
(四)Zend Performance Suite
http://www.zend.com/
   Zend Performance Suite是老牌的PHP加速/优化软件,依托于PHP领域最知名的Zend公司。目前已经推出4.0版本,它可以为PHP应用提供程序加速,内容缓存,文件压缩,下载服务等,功能十分强大,获得好几个PHP杂志的推荐奖—但是不得不提起,它也很昂贵,目前的价格是1875美元。
以上几种加速软件,希望读者按照服务器环境自行测试并选择其中最适用的,因为我没有办法提供一个普遍适用的测试标准来判断哪种方案是最有效的。综合起来看,我个人认为Turck MMCache是个值得推荐的选择,免费而且功能相当出色。

(四)总结

  以上从多个角度较为全面细致地阐述了PHP加速的相关技术,包括测试技术,加速技术(压缩,缓存等),基本上都有附代码和范例。希望本文有助于读者全面了解PHP程序加速并在实际应用中选择合适的加速方案。

Tags: ,
最近服务器运行生成静态页面的程序,总是报错,错误信息如下:
引用
Warning:  file_get_contents() [function.file-get-contents]: php_network_getaddresses: getaddrinfo failed: hostname nor servname provided, or not known in /data/www/vhost/5217u/plug-in/404/404.php on line 68



Warning:  file_get_contents(http://www.5217u.com/news/detail.php?id=6) [function.file-get-contents]: failed to open stream: Invalid argument in /data/www/vhost/5217u/plug-in/404/404.php on line 68

经查资料,发现错误是DNS的问题,域名无法解析,上服务器ping www.5217u.com得到错误信息,域名无法解析或者域名不存在,马上去查看resolv.conf,看到配置正确。
引用
domain  bizeway.com
nameserver      202.96.209.5
nameserver      202.96.209.133

但是在服务器上ping www.5217u.com就是不正常解析,在本地ping可以正常解析,经朋友了解,上海电信的域名服务器做了调整,对一部分ip不提供DNS服务了,原来问题出在电信。
后将配置文件修改如下:
引用
domain  bizeway.com
nameserver      202.96.209.133
nameserver      202.96.209.5

一切回复正常,希望大家以后再碰到“php_network_getaddresses: getaddrinfo failed: hostname nor servname provided”错误,不要动不动就去看程序哪里错了,换个DNS就好了。

这些数据可以让我们在做无线编程的时候,得心应手。
A600 Series
ACS-NF
Alcatel-BH4
Alcatel-BH4R
Alcatel-CTH3
Alcatel-M5
Alcatel-OH2
Alcatel-OT557
Alcatel-TH3
Alcatel-TH4
AMOI
Amoi-A211
Amoi-A310
Amoi-A320
Amoi-A650
Amoi-A660
Amoi-A9B
Amoi-CA6
Amoi-CA8
Amoi-CS6
Amoi-D8
Amoi-D80
Amoi-D85
Amoi-D86
Amoi-D89
Amoi-DA8
Amoi-DF9
Amoi-F6
Amoi-F60
Amoi-F8
Amoi-F90
Amoi-F99MY
Amoi-M350
Amoi-M6
Amoi-M630
Amoi-M8
Amoisonic-A9
Amoisonic-F9
Amoi-V800
Arima 2860 Profile
ASM-GEM
ASM-TUC
ASUS-J102
ASUS-V55
BBKK028
BenQ-M300
BenQ-M305
BenQ-M315
BenQ-M350
BENQ-NIKE1
BENQS660C
BENQS668C
BENQS680C
BENQS700\1.00\WAP2.0\MIDP2.0\CLDC1.0 UP.Browser
BenQ-Z2
Bird D200
BIRD D600
BIRD.A120 AU.Browser
BIRD.E859
BIRD.E860
BIRD.ES805
BIRD.G118 MO130m-128x160
BIRD.S310 MO130m-128x128
Bird.S689
Bird.S789+
Bird.S889
Bird.SC17C
BIRD.SC24 MO130m-128x160
Bird.SM10
BIRD.V59 MASV3-128x160
Bird.V69
Bird.V89
BIRD-DV10
Bird-S570
BIRD-V007
Bird-X8
BW-NEO200 TMT
Capitel
Capitel S750
Capitel-C8188
Capitel-F600
Capitel-F650
Capitel-G750
Capitel-V851
CECT A100
CECT A800
CECT G3200
CECT G3300
CECT N105
CECT T868
CECT V160
CECT V50
CECTQ6219
CECTs568
CECTT586
CK-PT01
Compal- V710
Compal-CECT-U100A
Compal-Compa
Compal-HZ8
Compal-HZ8C
Compal-TG762
Compal-TG762D
Compal-U8800
Compal-U8800A
Compal-U8810
Compal-V800C
COSUN-Q808
DAXIAN_D7199 CLDC
Daxian-D8000 CLDC
DBTEL
DBTELD5
DBTELT105
DBTELT302
DICAM-T905
DICAM-TG9A
Dnet-TG901
DNET-TGQ611OM
DNET-TGR602OJ
Dopod565 Mozilla
Dopod585
dopod586
Dopod828
E28-MPG1
EASTCOM-EG928
EASTCOM-ES1008
EASTCOM-ES1008A
EASTCOM-ES1009
EG309
EG670
EG900
EG908
EG910
EMOL-EL960
EricssonT39
EricssonT68
ESATCOM-ES2100
EV0608-Pandora
EZZE-ESL500
EZZE-EZZE
G910 UP.Browser
GMCC
GN606
GN608
GN638
Haier-M1000
Haier-M1210
Haier-M1600
HAIER-T3100
HAIER-T3110
HAIER-V100 ObigoInternetBrowser
HAIER-V8800
Haier-V9000
HAIER-Z300
HAIER-Z6100
HandSet 128160
Herojet-H828
http:
IAC
KBT UP.Browser
kejian-k358 UP.Browser
KEJIAN-K506
KEJIAN-K818
KONKA
KONKA_A19
KONKA_A59
KONKA-A66
KONKA-D180WAP2.0 MIDP
KONKA-T100
KONKA-V008
LENOVO
LENOVO-E307
LENOVO-E616
LENOVO-E700
LENOVO-I607
LENOVO-I660
LENOVO-i717
LENOVO-i816
LENOVO-i856
LENOVO-I950
LENOVO-P708
LENOVO-P710
LENOVO-P890
LENOVO-P902
LENOVO-P928
LENOVO-V520
LENOVO-V658
LENOVO-V707
LENOVO-V821
LENOVO-V830
LENOVO-V850
LENOVO-V858
LG-B2050 MIC
LG-C1100 MIC
LG-F2300 MIC
LG-G1800 MIC
LG-G210
LG-G220
LG-G232
LG-G233
LG-G252
LG-G262
LG-G282
LG-G5200 AU
LG-G5400 AU
LG-G610 V100 AU
LG-G622
LG-G650 V100 AU
LG-G660
LG-G672
LG-G682
LG-G688 MIC
LG-G7000 AU
LG-G7050 UP.Browser
LG-G7070 AU
LG-G7100 AU
LG-G7200 UP.Browser
LG-G822
LG-G828
LG-G850 V100 UP.Browser
LG-G912
LG-G920
LG-G932 UP.Browser
M4U
Mazilla
Mitsu
Mitsu-M520
Mitsu-M528
Mitsu-M530
Mitsu-M760
MOT-A668
MOT-A728
MOT-A760
MOT-A768
MOT-A780
MOT-A835
MOT-C155 UP.Browser
MOT-c350
MOT-c350M
MOT-c350V
MOT-C380
MOT-C450
MOT-C550
MOT-C650
MOT-C975
MOT-E1 iTunes
MOT-E1000
MOT-E375
MOT-E380
MOT-E398
MOT-E398B
MOT-E680
MOT-E680i
MOT-T720
MOT-T720M
MOT-TA02
MOT-v150
MOT-V171 UP.Browser
MOT-V180
MOT-V191
MOT-V220
MOT-V226
MOT-V290
MOT-V3
MOT-V300
MOT-V303
MOT-V360
MOT-V500
MOT-V501
MOT-V600
MOT-V600i
MOT-V60M
MOT-V620
MOT-V635
MOT-V690
MOT-V80
MOT-V872
MOT-V878
Mozilla
myTop-DV6
NEC-e1101
NEC-E232
NEC-N100
NEC-N108
NEC-N109
NEC-N110
NEC-N1101
NEC-N1102
NEC-N118
NEC-N150
NEC-N158
NEC-N160
NEC-N166
NEC-N168
NEC-N169
NEC-N170
NEC-N190
NEC-N200
NEC-N208
NEC-N3301
NEC-N500
NEC-N508
NEC-N5102
NEC-N600
NEC-N610
NEC-N620
NEC-N6201
NEC-N630
NEC-N700
NEC-N710
NEC-N718
NEC-N720
NEC-N728
NEC-N730
NEC-N738
NEC-N750
NEC-N8
NEC-N800
NEC-N810
NEC-N820
NEC-N830
NEC-N840
NEC-N850
NEC-N900
NEC-N919
NEC-N920
NEC-N930
NEC-N938
NEC-N940
Nokia2650
Nokia3100
Nokia3108
Nokia3120
Nokia3128
Nokia3200
Nokia3220
Nokia3230
Nokia3300
Nokia3510
Nokia3510i
Nokia3610
Nokia3650
Nokia3660
Nokia5100
Nokia5210
Nokia6020
Nokia6021
Nokia6030
Nokia6060
Nokia6100
Nokia6101
Nokia6102
Nokia6108
Nokia6170
Nokia6220
Nokia6230
Nokia6230i
Nokia6260
Nokia6510
Nokia6600
Nokia6610
Nokia6610I
Nokia6630
Nokia6670
Nokia6680
Nokia6681
Nokia6820
Nokia7200
Nokia7210
Nokia7250
Nokia7250I
Nokia7260
Nokia7270
Nokia7280
Nokia7600
Nokia7610
Nokia7650
Nokia8310
Nokia8800
Nokia8910i
NokiaN70-1
NokiaN90-1
NokiaN-GageQD
Optimay-Seville
Panasonic-A200
Panasonic-A210
Panasonic-A500
Panasonic-G50
Panasonic-G60
Panasonic-G70
Panasonic-GAD87
Panasonic-MX6
Panasonic-SA6
Panasonic-SC3
Panasonic-VS2
Panasonic-VS3
Panasonic-X100
Panasonic-X200P
Panasonic-X300
Panasonic-X400P
Panasonic-X500
Panasonic-X66
Panasonic-X70
Panasonic-X700
Panasonic-X77
Panasonic-X800
PANDA_GM958S
PANTECH_G670
PANTECH_GB200
PANTECH_PG-3000
PG-3200
PHILIPS 162
PHILIPS 163
PHILIPS 350
PHILIPS 355
PHILIPS 530
PHILIPS 535
PHILIPS 639
PHILIPS362-1 ObigoInternetBrowser
PHILIPS568
PHILIPS636 ObigoInternetBrowser
PHILIPS650 ObigoInternetBrowser
PHILIPS655 ObigoInternetBrowser
PHILIPS660 ObigoInternetBrowser
PHILIPS661 ObigoInternetBrowser
PHILIPS755 ObigoInternetBrowser
PHILIPS760 ObigoInternetBrowser
PHILIPS855 ObigoInternetBrowser
PHILIPS859 ObigoInternetBrowser
PHILIPS-SYSOL2
PHILIPS-SYSOL3
Poseidon
PT-G670 CLDC
PT-G800 CLDC
PT-G900 CLDC
PT-GF200J CLDC
PT-GI100J CLDC
QCI-33
RMA
S800 UP.Browser
SAGEM-myX5-2
SAGEM-myX-5m
SAGEM-myX-6
SamsungE600 UP.Browser
SAMSUNG-SGH-C218
SAMSUNG-SGH-C238
SAMSUNG-SGH-D488
SAMSUNG-SGH-D500C
SAMSUNG-SGH-D508
SAMSUNG-SGH-D608
SAMSUNG-SGH-E100A
SAMSUNG-SGH-E108
SAMSUNG-SGH-E330C
SAMSUNG-SGH-E338
SAMSUNG-SGH-E348
SAMSUNG-SGH-E350
SAMSUNG-SGH-E358
SAMSUNG-SGH-E568
SAMSUNG-SGH-E628
SAMSUNG-SGH-E630C
SAMSUNG-SGH-E638
SAMSUNG-SGH-E640
SAMSUNG-SGH-E648
SAMSUNG-SGH-E700A
SAMSUNG-SGH-E708
SAMSUNG-SGH-E728
SAMSUNG-SGH-E730
SAMSUNG-SGH-E738
SAMSUNG-SGH-E800C
SAMSUNG-SGH-E808
SAMSUNG-SGH-E838
SAMSUNG-SGH-E888
SAMSUNG-SGH-S508
SAMSUNG-SGH-T408
SAMSUNG-SGH-X100A
SAMSUNG-SGH-X108
SAMSUNG-SGH-X138
SAMSUNG-SGH-X208
SAMSUNG-SGH-X460C
SAMSUNG-SGH-X468
SAMSUNG-SGH-X478
SAMSUNG-SGH-X480C
SAMSUNG-SGH-X488
SAMSUNG-SGH-X600A
SAMSUNG-SGH-X608
SAMSUNG-SGH-X620C
SAMSUNG-SGH-X628
SAMSUNG-SGH-X640C
SAMSUNG-SGH-X648
SASTA686
SEC-SGHC200C
SEC-SGHD428
SEC-SGHE310C
SEC-SGHE318
SEC-SGHE530C
SEC-SGHE720C
SEC-SGHE810C
SEC-SGHP408
SEC-SGHP518
SEC-SGHP730C
SED-V68
SED-X505
SED-X520 ObigoInternetBrowser
SGH-E700
SHARP-TQ-GX10N
SHARP-TQ-GX12
SHARP-TQ-GX20N
SHARP-TQ-GX22
SHARP-TQ-GX22S
SHARP-TQ-GX32
SHARP-TQ-GX-T15
SHARP-TQ-GX-T25
SHARP-TQ-GX-T300
SHARP-TQ-GZ100S
SHARP-TQ-GZ200
SHARP-TQ-GZ200S
SHARP-TQ-V750
SIE-A65C
SIE-C60A
SIE-C62
SIE-C6C
SIE-C75
SIE-CF6C
SIE-CF7C
SIE-CX6C
SIE-CX7C
SIE-M55C
SIE-M55Z
SIE-M6C
SIE-MC6C
SIE-S57C
SIE-S6C
SIE-SF65
SIE-SL5C
SIE-SL6C
SIE-SX1
SIMCOM-M1
SonyEricssonJ200c
SonyEricssonJ210c
SonyEricssonJ300c
SonyEricssonJ300i
SonyEricssonK300c
SonyEricssonK300i
SonyEricssonK500c
SonyEricssonK500i
SonyEricssonK506c
SonyEricssonK508c
SonyEricssonK600c
SonyEricssonK600i
SonyEricssonK700c
SonyEricssonK700i
SonyEricssonK750c
SonyEricssonK750i
SonyEricssonK758c
SonyEricssonP800
SonyEricssonP900
SonyEricssonP910c
SonyEricssonP910i
SonyEricssonS700c
SonyEricssonS700i
SonyEricssonT230
SonyEricssonT238
SonyEricssonT290c
SonyEricssonT312
SonyEricssonT610
SonyEricssonT616
SonyEricssonT618
SonyEricssonT628
SonyEricssonT630
SonyEricssonT68
SonyEricssonW550c
SonyEricssonW550i
SonyEricssonW800c
SonyEricssonW800i
SonyEricssonZ1010
SonyEricssonZ200
SonyEricssonZ208
SonyEricssonZ520c
SonyEricssonZ600
SonyEricssonZ608
SonyEricssonZ800
Soutec-SG7610
Soyea
TCL-766
TCL-782
TCL-C318
TCL-D368
TCL-D668
TCL-D828
TCL-DE20
TCL-e737
TCL-E767
TCL-GM788
TCL-MOBO858
TCL-MOBO896
TCL-MOBO898
TCL-MOBO899
Telsda-T8003
Toplux AG280 Profile
V750
VIKING-V600
VK-VK2000
VK-VK700 UP.Browser
VK-VK800
VK-VK810
VK-VK900
Vulcan-Color UP.Browser
Y600 UP.Browser
YAS-COSMOS
ZTE-A96+
ZTE-A99
ZTE-E3
ZTE-G100
ZTE-G92
ZTETI
分页: 12/15 第一页 上页 7 8 9 10 11 12 13 14 15 下页 最后页 [ 显示模式: 摘要 | 列表 ]