Dereky's Blog

Don't be evil!

Subscribe to RSS feed

Apache 支持 wap

httpd.conf
最后增加:
#Wap MIME
AddType text/vnd.wap.wml .wml
AddType application/vnd.wap.wmlc .wmlc
AddType image/vnd.wap.wbmp .wbmp
AddType application/vnd.wap.wmlscriptc .wmlsc
AddType text/vnd.wap.wmlscript .wmls
AddType application/vnd.wap/wmlscriptc .wsc

重启apache:D

重采样拷贝部分图像并调整大小

imagecopyresampled

(PHP 4 >= 4.0.6, PHP 5)
imagecopyresampled -- 重采样拷贝部分图像并调整大小
说明
bool imagecopyresampled ( resource dst_image, resource src_image, int dst_x, int dst_y, int src_x, int src_y, int dst_w, int dst_h, int src_w, int src_h )

imagecopyresampled() 将一幅图像中的一块正方形区域拷贝到另一个图像中,平滑地插入像素值,因此,尤其是,减小了图像的大小而仍然保持了极大的清晰度。如果成功则返回 TRUE,失败则返回 FALSE。

dst_image 和 src_image 分别是目标图像和源图像的标识符。如果源和目标的宽度和高度不同,则会进行相应的图像收缩和拉伸。坐标指的是左上角。本函数可用来在同一幅图内部拷贝(如果 dst_image 和 src_image 相同的话)区域,但如果区域交迭的话则结果不可预知。

注: 因为调色板图像限制(255+1 种颜色)有个问题。重采样或过滤图像通常需要多于 255 种颜色,计算新的被重采样的像素及其颜色时采用了一种近似值。对调色板图像尝试分配一个新颜色时,如果失败我们选择了计算结果最接近(理论上)的颜色。这并不总是视觉上最接近的颜色。这可能会产生怪异的结果,例如空白(或者视觉上是空白)的图像。要跳过这个问题,请使用真彩色图像作为目标图像,例如用 imagecreatetruecolor() 创建的。

注: 本函数需要 GD 2.0.1 或更高版本。

范例

例子 1. 简单例子

本例中将把一幅图像重采样为原始大小的一半。
<?php
// The file
$filename = 'test.jpg';
$percent = 0.5;

// Content type
header('Content-type: image/jpeg');

// Get new dimensions
list($width, $height) = getimagesize($filename);
$new_width = $width * $percent;
$new_height = $height * $percent;

// Resample
$image_p = imagecreatetruecolor($new_width, $new_height);
$image = imagecreatefromjpeg($filename);
imagecopyresampled($image_p, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);

// Output
imagejpeg($image_p, null, 100);
?>

例子 2. 按比例重采样图像

本例将把一幅图像按最宽或最高 200 像素来显示。
<?php
// The file
$filename = 'test.jpg';

// Set a maximum height and width
$width = 200;
$height = 200;

// Content type
header('Content-type: image/jpeg');

// Get new dimensions
list($width_orig, $height_orig) = getimagesize($filename);

if ($width && ($width_orig < $height_orig)) {
$width = ($height / $height_orig) * $width_orig;
} else {
$height = ($width / $width_orig) * $height_orig;
}

// Resample
$image_p = imagecreatetruecolor($width, $height);
$image = imagecreatefromjpeg($filename);
imagecopyresampled($image_p, $image, 0, 0, 0, 0, $width, $height, $width_orig, $height_orig);

// Output
imagejpeg($image_p, null, 100);
?>

使用javascript对cookie的读写


function GetCookieVal(offset)
//获得Cookie解码后的值
{
var endstr = document.cookie.indexOf (";", offset);
if (endstr == -1)
endstr = document.cookie.length;
return unescape(document.cookie.substring(offset, endstr));
}
function SetCookie(name, value)
//设定Cookie值
{
var expdate = new Date();
var argv = SetCookie.arguments;
var argc = SetCookie.arguments.length;
var expires = (argc > 2) ? argv[2] : null;
var path = (argc > 3) ? argv[3] : null;
var domain = (argc > 4) ? argv[4] : null;
var secure = (argc > 5) ? argv[5] : false;
if(expires!=null) expdate.setTime(expdate.getTime() + ( expires * 1000 ));
document.cookie = name + "=" + escape (value) +((expires == null) ? "" : ("; expires="+ expdate.toGMTString()))
+((path == null) ? "" : ("; path=" + path)) +((domain == null) ? "" : ("; domain=" + domain))
+((secure == true) ? "; secure" : "");
}
function DelCookie(name)
//删除Cookie
{
var exp = new Date();
exp.setTime (exp.getTime() - 1);
var cval = GetCookie (name);
document.cookie = name + "=" + cval + "; expires="+ exp.toGMTString();
}
function GetCookie(name)
//获得Cookie的原始值
{
var arg = name + "=";
var alen = arg.length;
var clen = document.cookie.length;
var i = 0;
while (i < clen)
{
var j = i + alen;
if (document.cookie.substring(i, j) == arg)
return GetCookieVal (j);
i = document.cookie.indexOf(" ", i) + 1;
if (i == 0) break;
}
return null;
}

windows中让PHP支持CURL

1、拷贝PHP目录中的libeay32.dll 和 ssleay32.dll 两个文件到 system32 目录。
2、修改php.ini:配置好 extension_dir ,去掉 extension = php_curl.dll 前面的分号。
3、重新启动Apache。

Mysql 数据库双机热备的配置

1。mysql数据库没有增量备份的机制,当数据量太大的时候备份是一个很大的问题。还好mysql数据库提供了一种主从备份的机制,其实就是把主数据库的所有的数据同时写到备份数据库中。实现mysql数据库的热备份。

2。要想实现双机的热备首先要了解主从数据库服务器的版本的需求。要实现热备mysql的版本都要高于3.2,还有一个基本的原则就是作为从数据库的数据库版本可以高于主服务器数据库的版本,但是不可以低于主服务器的数据库版本。

3。设置主数据库服务器:

a.首先查看主服务器的版本是否是支持热备的版本。然后查看my.cnf(类unix)或者my.ini(windows)中mysqld配置块的配置有没有log-bin(记录数据库更改日志),因为mysql的复制机制是基于日志的复制机制,所以主服务器一定要支持更改日志才行。然后设置要写入日志的数据库或者不要写入日志的数据库。这样只有您感兴趣的数据库的更改才写入到数据库的日志中。

server-id=1 //数据库的id这个应该默认是1就不用改动

log-bin=log_name //日志文件的名称,这里可以制定日志到别的目录 如果没有设置则默认主机名的一个日志名称

binlog-do-db=db_name //记录日志的数据库

binlog-ignore-db=db_name //不记录日志的数据库

以上的如果有多个数据库用","分割开

然后设置同步数据库的用户帐号

mysql> GRANT REPLICATION SLAVE ON *.*

-> TO 'repl'@'%.mydomain.com' IDENTIFIED BY 'slavepass';

4.0.2以前的版本, 因为不支持REPLICATION 要使用下面的语句来实现这个功能

mysql> GRANT FILE ON *.*

-> TO 'repl'@'%.mydomain.com' IDENTIFIED BY 'slavepass';

设置好主服务器的配置文件后重新启动数据库

b.锁定现有的数据库并备份现在的数据

锁定数据库

mysql> FLUSH TABLES WITH READ LOCK;

备份数据库有两种办法一种是直接进入到mysql的data目录然后打包你需要备份数据库的文件夹,第二种是使用mysqldump的方式来备份数据库但是要加上"--master-data " 这个参数,建议使用第一种方法来备份数据库

c.查看主服务器的状态

mysql> show master status\G;

+---------------+----------+--------------+------------------+

| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |

+---------------+----------+--------------+------------------+

| mysql-bin.003 | 73 | test | manual,mysql |

+---------------+----------+--------------+------------------+

记录File 和 Position 项目的值,以后要用的。

d.然后把数据库的锁定打开

mysql> UNLOCK TABLES;

4。设置从服务器

a.首先设置数据库的配置文件

server-id=n //设置数据库id默认主服务器是1可以随便设置但是如果有多台从服务器则不能重复。

master-host=db-master.mycompany.com //主服务器的IP地址或者域名

master-port=3306 //主数据库的端口号

master-user=pertinax //同步数据库的用户

master-password=freitag //同步数据库的密码

master-connect-retry=60 //如果从服务器发现主服务器断掉,重新连接的时间差

report-host=db-slave.mycompany.com //报告错误的服务器

b.把从主数据库服务器备份出来的数据库导入到从服务器中

c.然后启动从数据库服务器,如果启动的时候没有加上"--skip-slave-start"这个参数则进入到mysql中

mysql> slave stop; //停止slave的服务

d.设置主服务器的各种参数

mysql> CHANGE MASTER TO

-> MASTER_HOST='master_host_name', //主服务器的IP地址

-> MASTER_USER='replication_user_name', //同步数据库的用户

-> MASTER_PASSword='replication_password', //同步数据库的密码

-> MASTER_LOG_FILE='recorded_log_file_name', //主服务器二进制日志的文件名(前面要求记住的参数)

-> MASTER_LOG_POS=recorded_log_position; //日志文件的开始位置(前面要求记住的参数)

e.启动同步数据库的线程

mysql> slave start;

查看数据库的同步情况吧。如果能够成功同步那就恭喜了!

查看主从服务器的状态

mysql> SHOW PROCESSLIST\G //可以查看mysql的进程看看是否有监听的进程

如果日志太大清除日志的步骤如下

1.锁定主数据库

mysql> FLUSH TABLES WITH READ LOCK;

2.停掉从数据库的slave

mysql> slave stop;

3.查看主数据库的日志文件名和日志文件的position

show master status;

+---------------+----------+--------------+------------------+

| File | Position | Binlog_do_db | Binlog_ignore_db |

+---------------+----------+--------------+------------------+

| louis-bin.001 | 79 | | mysql |

+---------------+----------+--------------+------------------+

4.解开主数据库的锁

mysql> unlock tables;

5.更新从数据库中主数据库的信息

mysql> CHANGE MASTER TO

-> MASTER_HOST='master_host_name', //主服务器的IP地址

-> MASTER_USER='replication_user_name', //同步数据库的用户

-> MASTER_PASSword='replication_password', //同步数据库的密码

-> MASTER_LOG_FILE='recorded_log_file_name', //主服务器二进制日志的文件名(前面要求记住的参数)

-> MASTER_LOG_POS=recorded_log_position; //日志文件的开始位置(前面要求记住的参数)

6.启动从数据库的slave

mysql> slave start;

用PHP5的SimpleXML解析XML文档

messages.xml ======================================================== <?xml version="1.0" ?> <SystemMessage>      <MessageTitle>System Down for Maintenance</MessageTitle>     <MessageBody>Going down for maintenance soon!</MessageBody>     <MessageAuthor>    <MessageAuthorName>Joe SystemGod</MessageAuthorName>    <MessageAuthorEmail>systemgod@someserver.com </MessageAuthorEmail>     </MessageAuthor>     <MessageDate>March 4, 2004</MessageDate>    <MessageNumber>10</MessageNumber> </SystemMessage> ======================================================== xml 是一种创建元数据的语言,元数据是描述其它数据的数据,PHP中的XML处理是基于LIBXML2的,安装时默认开启。 可以通过phpinfo()函数查看是否开启了XML处理模块,DOM,LIBXML,SAMPLEXML。 首先,通过samplexml_load_file函数把xml文件加载到一个对象中,samplexml_load_file可以用户远程文件. 例如: $xml = samplexml_load_file("messages.xml"); // 本地文件系统,当前目录 $xml = samplexml_load_file("http://www.xml.org.cn/messages.xml"); // 远程web服务器 用 var_dump($xml) 和 print_r($xml) 分别输出其结构.var_dump给出了变量的类型和长度,而print_r可读性更强 输出对象中的所有元素名称和它的值. echo $xml->MessageTitle; //输出消息的标题 echo $xml->MessageBody; // 输出消息体 echo $xml->MessageAuthor; //消息的作者 echo $xml->MessageDate;  // 消息产生的日期 echo $xml->MessageNumber;  // 消息代码 =================================================== 另外,还有一个函数,可以把XML字符串加载到一个simplexml对象中取 $channel =<<<_XML_ <channel> What's For Dinner <link>http://menu.example.com/</link> <description>These are your choices of what to eat tonight. </description> </channel> _XML_; $xml = simplexml_load_string($channel); =================================================== rss.xml ============================================= <?xml version="1.0" encoding="utf-8"?> <rss version="0.91"> <channel>  What's For Dinner  <link>http://menu.example.com/</link>  <description>These are your choices of what to eat tonight.</description>  <item>   Braised Sea Cucumber   <link>http://menu.example.com/dishes.php?dish=cuke</link>   <description>Gentle flavors of the sea that nourish and refresh you. </description>  </item>  <item>   Baked Giblets with Salt   <link>http://menu.example.com/dishes.php?dish=giblets</link>   <description>Rich giblet flavor infused with salt and spice. </description>  </item>  <item>   Abalone with Marrow and Duck Feet   <link>http://menu.example.com/dishes.php?dish=abalone</link>   <description>There's no mistaking the special pleasure of abalone. </description>  </item> </channel> </rss> ===================================================== 1.访问具有相同元素名称的节点 2.通过foreach循环所有相同元素名称的子节点 foreach($xml->channel->item as $key=>$value) { print "Title: " . $item->title . "\n"; } 3.输出整个文档 echo $xml->asXML(); 4.把节点作为字符串输出 echo $xml->channel->item[0]->asXML(); 这将输出文本 <item> Braised Sea Cucumber <link>http://menu.example.com/dishes.php?dish=cuke</link> <description>Gentle flavors of the sea that nourish and refresh you. </description> </item> 带文件名参数的asXML将会把原本输出的内容保存为一个文件 $xml->channel->item[0]->asXML("item[0].xml"); 完整的代码: rss.xml ===== <?xml version="1.0" encoding="utf-8"?> <rss version="0.91"> <channel>  What's For Dinner  <link>http://menu.example.com/</link>  <description>These are your choices of what to eat tonight.</description>  <item>   Braised Sea Cucumber   <link>http://menu.example.com/dishes.php?dish=cuke</link>   <description>Gentle flavors of the sea that nourish and refresh you. </description>  </item>  <item>   Baked Giblets with Salt   <link>http://menu.example.com/dishes.php?dish=giblets</link>   <description>Rich giblet flavor infused with salt and spice. </description>  </item>  <item>   Abalone with Marrow and Duck Feet   <link>http://menu.example.com/dishes.php?dish=abalone</link>   <description>There's no mistaking the special pleasure of abalone. </description>  </item> </channel> </rss> rss.php ====== <?php $xml = simplexml_load_file("rss.xml"); echo "

".$xml->channel->title."


"; echo "
    "; echo "
  • Title:".$xml->channel->item[0]->title."
  • "; echo "
  • Title:".$xml->channel->item[1]->title."
  • "; echo "
  • Title:".$xml->channel->item[2]->title."
  • "; echo "
"; print "Title: " . $xml->channel->item[0]->title . "\n
"; print "Title: " . $xml->channel->item[1]->title . "\n
"; print "Title: " . $xml->channel->item[2]->title . "\n
"; echo "
"; foreach ($xml->channel->item[0] as $element_name => $content) {   print "The $element_name is $content\n
"; } echo "
"; print_r($xml); echo $xml->channel->item[0]->asXML(); ?> 任何XML文本在输出前最好用 htmlentiteis() 函数编码后再输出,否这可能出现问题

MySQL 实现 Ms SQL 的 sp_executesql

从MySQL 5.0 开始,
支持了一个全新的SQL句法:

PREPARE stmt_name FROM preparable_stmt;

EXECUTE stmt_name [USING @var_name [, @var_name] ...];

{DEALLOCATE | DROP} PREPARE stmt_name;



通过它,我们就可以实现类似 MS SQL 的 sp_executesql 执行动态SQL语句!
同时也可以防止注入式攻击!

为了有一个感性的认识,
下面先给几个小例子:



mysql> PREPARE stmt1 FROM 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';
mysql> SET @a = 3;
mysql> SET @b = 4;
mysql> EXECUTE stmt1 USING @a, @b;
+------------+
| hypotenuse |
+------------+
| 5 |
+------------+
mysql> DEALLOCATE PREPARE stmt1;

mysql> SET @s = 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';
mysql> PREPARE stmt2 FROM @s;
mysql> SET @a = 6;
mysql> SET @b = 8;
mysql> EXECUTE stmt2 USING @a, @b;
+------------+
| hypotenuse |
+------------+
| 10 |
+------------+
mysql> DEALLOCATE PREPARE stmt2;


如果你的MySQL 版本是 5.0.7 或者更高的,你还可以在 LIMIT 子句中使用它,示例如下:mysql> SET @a=1;mysql> PREPARE STMT FROM "SELECT * FROM tbl LIMIT ?";
mysql> EXECUTE STMT USING @a;
mysql> SET @skip=1; SET @numrows=5;
mysql> PREPARE STMT FROM "SELECT * FROM tbl LIMIT ?, ?";
mysql> EXECUTE STMT USING @skip, @numrows; 使用 PREPARE 的几个注意点:A:
PREPARE stmt_name FROM preparable_stmt;
预定义一个语句,并将它赋给 stmt_name ,stmt_name 是不区分大小写的。B: 即使 preparable_stmt 语句中的 ? 所代表的是一个字符串,你也不需要将 ? 用引号包含起来。C: 如果新的 PREPARE 语句使用了一个已存在的 stmt_name ,那么原有的将被立即释放! 即使这个新的 PREPARE 语句因为错误而不能被正确执行。D: PREPARE stmt_name 的作用域是当前客户端连接会话可见。E: 要释放一个预定义语句的资源,可以使用 DEALLOCATE PREPARE 句法。F: EXECUTE stmt_name 句法中,如果 stmt_name 不存在,将会引发一个错误。 G: 如果在终止客户端连接会话时,没有显式地调用 DEALLOCATE PREPARE 句法释放资源,服务器端会自己动释放它。H: 在预定义语句中,CREATE TABLE, DELETE, DO, INSERT, REPLACE, SELECT, SET, UPDATE, 和大部分的 SHOW 句法被支持。G: PREPARE 语句不可以用于存储过程,自定义函数!但从 MySQL 5.0.13 开始,它可以被用于存储过程,仍不支持在函数中使用! 下面给个示例: CREATE PROCEDURE `p1`(IN id INT UNSIGNED,IN name VARCHAR(11))BEGIN lable_exit: BEGIN SET @SqlCmd = 'SELECT * FROM tA '; IF id IS NOT NULL THEN SET @SqlCmd = CONCAT(@SqlCmd , 'WHERE id=?'); PREPARE stmt FROM @SqlCmd; SET @a = id; EXECUTE stmt USING @a; LEAVE lable_exit; END IF; IF name IS NOT NULL THEN SET @SqlCmd = CONCAT(@SqlCmd , 'WHERE name LIKE ?'); PREPARE stmt FROM @SqlCmd; SET @a = CONCAT(name, '%'); EXECUTE stmt USING @a; LEAVE lable_exit; END IF; END lable_exit;END; CALL `p1`(1,NULL);CALL `p1`(NULL,'QQ');DROP PROCEDURE `p1`;

可恶的中国移动!简直是打劫啊!

最近因为老是要外出,买了一个多普达900
发现这个机器操作巨复杂,亏自己还玩电脑这么多年了,不知道要是那些看到电脑会昏的用户是怎么使用的(PS:老婆捎带着买了一个585,买来直接晕了,使用任何功能对她来说就是大叫:来帮帮看看这个怎么搞....)
为了上网方便,去买了一个据说非常划算的动感地带卡,带了一个所谓的任我行套餐,5元包所有GPRS流量,但是只能是通过cmwap上网....
不懂呀(吃了没文化的亏)!!第一次接触手机上网,哪知道什么cmwap和cmnet啊!Google一下,发现两个东东原本是一样的,只是中国移动人为的区分了,目的不言而明:为了多收费!BS一下!按照GOOGLE的观点,这是不是属于作恶的企业:irked:
cmwap就cmwap吧,反正能上就行,于是乐颠颠的开始玩,觉得新玩具还是蛮好的,起码我有点爱上坐公共汽车了,一路上可以慢慢的浏览下网站,阅读RSS什么的...
直到今天下午,一条短消息吓我一大跳:您的手机费用已不足10元,请尽快充值...
昏倒!这才几天啊,我刚充的100元就没了,因为以前的CDMA还在用,我还没打过任何电话呢!于是赶紧上网去查费用明细,不看不要紧一看吓一跳,GPRS费用98元...初以为是不是移动搞错了啊,赶紧打1860
小姐的声音是甜美的,语气是不容置疑的:先生,是这样的,当您使用手机浏览WAP站点的时候,您的流量是免费的,当您浏览其他www网站的时候,系统会自动切换到cmnet去,使用cmnet的费用是0.03/K....
scared scared 简直抓狂了,居然还是“自动的”!同时小姐还甜美的告诉我,我们是不能帮您停止cmnet服务的,除非您把所有的上网服务都取消....scared :insane:继续抓狂...
没有了www服务,不能上MSN不能QQ,不能信箱...那我要这个东西做什么?天天浏览什么QQ的世纪疯?还是那个永远也上不去的wap.monternet.com啊?
一怒之下继续Google,搞了一晚上,终于搞定:手动删除所有的连接设置,只增加一条:cmwap,设置默认的通讯规则为他!安装一个代理,拦截所有的出站(呵呵,PC用语,不知道PPC上该叫什么),转发到HTTP代理去...
测试msn通过,测试QQ,通过...
登陆移动网站查费用,终于不再扣钱了...这个世界清净了:rolleyes:
中国移动,看你再骗我钱!这个骗子企业:irked:

PHP5中的SOAP方式

server.php:
<?php
function getQuote($fpsecode) {
global $dbh;
$result = array();
try {
$query = "SELECT fprice, fcansale, fbalance, fbaltip FROM tblbalance where upper(trim(fpsecode)) = :psecode limit 1";
$stmt = $dbh->prepare($query);
$stmt->execute(array(’:psecode’ => strtoupper(trim($fpsecode))));
$stmt->bindColumn(’fprice’, $fprice);
$stmt->bindColumn(’fcansale’, $fcansale);
$stmt->bindColumn(’fbalance’, $fbalance);
$stmt->bindColumn(’fbaltip’, $fbaltip);
while($row = $stmt->fetch(PDO_FETCH_BOUND)) {
//
}
} catch (PDOException $e) {
echo $e->getMessage();
}
return $fprice; //你可以返回一个数组
}

$dsn = ’pgsql:host=192.168.*.* port=5432 dbname=db user=123456 password=123456’;
try {
$dbh = new PDO($dsn);
} catch (PDOException $e) {
die(’Connection failed: ’ . $e->getMessage());
}
ini_set("soap.wsdl_cache_enabled", "0"); // disabling WSDL cache
$server = new SoapServer("stockquote.wsdl"); //配置文件
$server->addFunction("getQuote");
$server->handle();
?>


   stockquote.wsdl:
<?xml version =’1.0’ encoding =’UTF-8’ ?>
<definitions name=’StockQuote’
targetNamespace=’http://example.org/StockQuote
xmlns:tns=’ http://example.org/StockQuote
xmlns:soap=’http://schemas.xmlsoap.org/wsdl/soap/
xmlns:xsd=’http://www.w3.org/2001/XMLSchema
xmlns:soapenc=’http://schemas.xmlsoap.org/soap/encoding/
xmlns:wsdl=’http://schemas.xmlsoap.org/wsdl/
xmlns=’http://schemas.xmlsoap.org/wsdl/’>

<message name=’getQuoteRequest’>
<part name=’symbol’ type=’xsd:string’/>
</message>
<message name=’getQuoteResponse’>
<part name=’Result’ type=’xsd:float’/>
</message>

<portType name=’StockQuotePortType’>
<operation name=’getQuote’>
<input message=’tns:getQuoteRequest’/>
<output message=’tns:getQuoteResponse’/>
</operation>
</portType>

<binding name=’StockQuoteBinding’ type=’tns:StockQuotePortType’>
<soap:binding style=’rpc’
transport=’http://schemas.xmlsoap.org/soap/http’/>
<operation name=’getQuote’>
<soap:operation soapAction=’urn:xmethods-delayed-quotes#getQuote’/>
<input>
<soap:body use=’encoded’ namespace=’urn:xmethods-delayed-quotes’
encodingStyle=’http://schemas.xmlsoap.org/soap/encoding/’/>
</input>
<output>
<soap:body use=’encoded’ namespace=’urn:xmethods-delayed-quotes’
encodingStyle=’http://schemas.xmlsoap.org/soap/encoding/’/>
</output>
</operation>
</binding>

<service name=’StockQuoteService’>
<port name=’StockQuotePort’ binding=’StockQuoteBinding’>
<soap:address location=’http://192.168.3.9/php5/server.php’/>
</port>
</service>
</definitions>


client.php:
<?php
$client = new SoapClient("stockquote.wsdl");
$result = $client->getQuote("nde005");
print_r($result);
?>

PHP5中的SOAP方式.txt

PHP 实现多服务器共享 SESSION 数据

一、问题起源
稍大一些的网站,通常都会有好几个服务器,每个服务器运行着不同功能的模块,使用不同的二级域名,而一个整体性强的网站,用户系统是统一的,即一套用户名、密码在整个网站的各个模块中都是可以登录使用的。各个服务器共享用户数据是比较容易实现的,只需要在后端放个数据库服务器,各个服务器通过统一接口对用户数据进行访问即可。但还存在一个问题,就是用户在这个服务器登录之后,进入另一个服务器的别的模块时,仍然需要重新登录,这就是一次登录,全部通行的问题,映射到技术上,其实就是各个服务器之间如何实现共享 SESSION 数据的问题。

二、PHP SESSION 的工作原理
在解决问题之前,先来了解一下 PHP SESSION 的工作原理。在客户端(如浏览器)登录网站时,被访问的 PHP 页面可以使用 session_start() 打开 SESSION,这样就会产生客户端的唯一标识 SESSION ID(此 ID 可通过函数 session_id() 获取/设置)。SESSION ID 可以通过两种方式保留在客户端,使得请求不同的页面时,PHP 程序可以获知客户端的 SESSION ID;一种是将 SESSION ID 自动加入到 GET 的 URL 中,或者 POST 的表单中,默认情况下,变量名为 PHPSESSID;另一种是通过 COOKIE,将 SESSION ID 保存在 COOKIE 中,默认情况下,这个 COOKIE 的名字为 PHPSESSID。这里我们主要以 COOKIE 方式进行说明,因为应用比较广泛。
那么 SESSION 的数据保存在哪里呢?当然是在服务器端,但不是保存在内存中,而是保存在文件或数据库中。默认情况下,php.ini 中设置的 SESSION 保存方式是 files(session.save_handler = files),即使用读写文件的方式保存 SESSION 数据,而 SESSION 文件保存的目录由 session.save_path 指定,文件名以 sess_ 为前缀,后跟 SESSION ID,如:sess_c72665af28a8b14c0fe11afe3b59b51b。文件中的数据即是序列化之后的 SESSION 数据了。如果访问量大,可能产生的 SESSION 文件会比较多,这时可以设置分级目录进行 SESSION 文件的保存,效率会提高很多,设置方法为:session.save_path="N;/save_path",N 为分级的级数,save_path 为开始目录。当写入 SESSION 数据的时候,PHP 会获取到客户端的 SESSION_ID,然后根据这个 SESSION ID 到指定的 SESSION 文件保存目录中找到相应的 SESSION 文件,不存在则创建之,最后将数据序列化之后写入文件。读取 SESSION 数据是也是类似的操作流程,对读出来的数据需要进行解序列化,生成相应的 SESSION 变量。

三、多服务器共享 SESSION 的主要障碍及解决办法
通过了解 SESSION 的工作原理,我们可以发现,在默认情况下,各个服务器会各自分别对同
一个客户端产生 SESSION ID,如对于同一个用户浏览器,A 服务器产生的 SESSION ID 是 30de1e9de3192ba6ce2992d27a1b6a0a,而 B 服务器生成的则是 c72665af28a8b14c0fe11afe3b59b51b。另外,PHP 的 SESSION 数据都是分别保存在
本服务器的文件系统中。如下图所示:

确定了问题所在之后,就可以着手进行解决了。想要共享 SESSION 数据,那就必须实现两个目标:一个是各个服务器对同一个客户端产生的 SESSION ID 必须相同,并且可通过同一个 COOKIE 进行传递,也就是说各个服务器必须可以读取同一个名为 PHPSESSID 的 COOKIE;
另一个是 SESSION 数据的存储方式/位置必须保证各个服务器都能够访问到。简单地说就是多服务器共享客户端的 SESSION ID,同时还必须共享服务器端的 SESSION 数据。

第一个目标的实现其实很简单,只需要对 COOKIE 的域(domain)进行特殊地设置即可,
默认情况下,COOKIE 的域是当前服务器的域名/IP 地址,而域不同的话,各个服务器所设
置的 COOKIE 是不能相互访问的,如