用PHP的ob_start();控制您的浏览器cache!

Output Control 函数可以让你自由控制脚本中数据的输出。它非常地有用,特别是对于:当你想在数据已经输出后,再输出文件头的情况。输出控制函数不对使用 header() 或 setcookie(), 发送的文件头信息产生影响,只对那些类似于 echo() 和 PHP 代码的数据块有作用。

我们先举一个简单的例子,让大家对Output Control有一个大致的印象:
Example 1.


所有对header()函数有了解的人都知道,这个函数会发送一段文件头给浏览器,但是如果在使用这个函数之前已经有了任何输出(包括空输出,比如空格,回车和换行)就会提示出错。如果我们去掉第一行的ob_start(),再执行此程序,我们会发现得到了一条错误提示:"Header had all ready send by"!但是加上ob_start,就不会提示出错,原因是当打开了缓冲区,echo后面的字符不会输出到浏览器,而是保留在服务器,直到你使用 flush或者ob_end_flush才会输出,所以并不会有任何文件头输出的错误!


一、 相关函数简介:
1、Flush:刷新缓冲区的内容,输出。
函数格式:flush()
说明:这个函数经常使用,效率很高。
2、ob_start :打开输出缓冲区
函数格式:void ob_start(void)
说明:当缓冲区激活时,所有来自PHP程序的非文件头信息均不会发送,而是保存在内部缓冲区。为了输出缓冲区的内容,可以使用ob_end_flush()或flush()输出缓冲区的内容。
3 、ob_get_contents :返回内部缓冲区的内容。
使用方法:string ob_get_contents(void)
说明:这个函数会返回当前缓冲区中的内容,如果输出缓冲区没有激活,则返回 FALSE 。
4、ob_get_length:返回内部缓冲区的长度。
使用方法:int ob_get_length(void)
说明:这个函数会返回当前缓冲区中的长度;和ob_get_contents一样,如果输出缓冲区没有激活。则返回 FALSE。
5、ob_end_flush :发送内部缓冲区的内容到浏览器,并且关闭输出缓冲区。
使用方法:void ob_end_flush(void)
说明:这个函数发送输出缓冲区的内容(如果有的话)。
6、ob_end_clean:删除内部缓冲区的内容,并且关闭内部缓冲区
使用方法:void ob_end_clean(void)
说明:这个函数不会输出内部缓冲区的内容而是把它删除!
7、ob_implicit_flush:打开或关闭绝对刷新
使用方法:void ob_implicit_flush ([int flag])
说明:使用过Perl的人都知道$|=x的意义,这个字符串可以打开/关闭缓冲区,而ob_implicit_flush函数也和那个一样,默认为关闭缓冲区,打开绝对输出后,每个脚本输出都直接发送到浏览器,不再需要调用 flush()


二、深入了解:

1. 关于Flush函数:
这个函数在PHP3中就出现了,是一个效率很高的函数,他有一个非常有用的功能就是刷新browser的cache.我们举一个运行效果非常明显的例子来说明flush.
Example 2.

CODE<?php
for($i = 1; $i <= 300; $i++ ) print(" ");
// 这一句话非常关键,cache的结构使得它的内容只有达到一定的大小才能从浏览器里输出
// 换言之,如果cache的内容不达到一定的大小,它是不会在程序执行完毕前输出的。经
// 过测试,我发现这个大小的底限是256个字符长。这意味着cache以后接收的内容都会
// 源源不断的被发送出去。
For($j = 1; $j <= 20; $j++) {
echo $j."
";
flush(); //这一部会使cache新增的内容被挤出去,显示到浏览器上
sleep(1); //让程序"睡"一秒钟,会让你把效果看得更清楚
}
?>


具体效果你可以到这里看看http://www.php2000.com/~uchinaboy/out.php
PHP2000的最新的PHP聊天室就是用的这个技术,可惜的是源代码未公开 L
注:如果在程序的首部加入ob_implicit_flush()打开绝对刷新,就可以在程序中不再使用flush(),这样做的好处是:提高效率!

2. 关于ob系列函数:
我想先引用我的好朋友y10k的一个例子:
Example 3.

比如你用得到服务器和客户端的设置信息,但是这个信息会因为客户端的不同而不同,如果想要保存phpinfo()函数的输出怎么办呢?在没有缓冲区控制之前,可以说一点办法也没有,但是有了缓冲区的控制,我们可以轻松的解决:
CODE<?php
ob_start(); //打开缓冲区
phpinfo(); //使用phpinfo函数
$info=ob_get_contents(); //得到缓冲区的内容并且赋值给$info
$file=fopen(\'info.txt\',\'w\'); //打开文件info.txt
fwrite($file,$info); //写入信息到info.txt
fclose($file); //关闭文件info.txt
?>


用以上的方法,就可以把不同用户的phpinfo信息保存下来,这在以前恐怕没有办法办到!其实上面就是将一些"过程"转化为"函数"的方法!
或许有人会问:"难道就这个样子吗?还有没有其他用途?"当然有了,比如笔者论坛的PHP 语法加亮显示就和这个有关(PHP默认的语法加亮显示函数会直接输出,不能保存结果,如果在每次调用都显示恐怕会很浪费CPU,笔者的论坛就把语法加亮函数显示的结果用控制缓冲区的方法保留了),大家如果感兴趣的话可以来看看http://www.zphp.com/bbs/

可能现在大家对ob_start()的功能有了一定的了解,上面的一个例子看似简单,但实际上已经掌握了使用ob_start()的要点。
<1>.使用ob_start打开browser的cache,这样可以保证cache的内容在你调用flush(),ob_end_flush()(或程序执行完毕)之前不会被输出。
< 2>.现在的你应该知道你所拥有的优势:可以在任何输出内容后面使用header,setcookie以及session,这是ob_start一个很大的特点;也可以使用ob_start的参数,在cache被写入后,然后自动运行命令,比如ob_start(\"ob_gzhandler\ ");而我们最常用的做法是用ob_get_contents()得到cache中的内容,然后再进行处理……
<3>.当处理完毕后,我们可以使用各种方法输出,flush(),ob_end_flush(),以及等到程序执行完毕后的自动输出。当然,如果你用的是ob_get_contents(),那么就要你自己控制输出方式了。

来,让我们看看能用ob系列函数做些什么……

一、 静态模版技术

简介:所谓静态模版技术就是通过某种方式,使得用户在client端得到的是由PHP产生的html页面。如果这个html页面不会再被更新,那么当另外的用户再次浏览此页面时,程序将不会再调用PHP以及相关的数据库,对于某些信息量比较大的网站,例如sina,163,sohu。类似这种的技术带来的好处是非常巨大的。

我所知道的实现静态输出的有两种办法:
<1>.通过y10k修改的phplib的一个叫template.inc.php类实现。
<2>.使用ob系列函数实现。
对于第一种方法,因为不是这篇文章所要研究的问题,所以不再赘述。
我们现在来看一看第二种方法的具体实现:
Example 4.


CODE<?php
ob_start();//打开缓冲区
?>
php页面的全部输出
<?
$content = ob_get_contents();//取得php页面输出的全部内容
$fp = fopen("output00001.html", "w"); //创建一个文件,并打开,准备写入
fwrite($fp, $content); //把php页面的内容全部写入output00001.html,然后……
fclose($fp);
?>

这样,所谓的静态模版就很容易的被实现了……

二、 捕捉输出

以上的Example 4.是一种最简单的情况,你还可以在写入前对$content进行操作……
你可以设法捕捉一些关键字,然后去对它进行再处理,比如Example 3.所述的PHP语法高亮显示。个人认为,这个功能是此函数最大的精华所在,它可以解决各种各样的问题,但需要你有足够的想象力……
Example 5.

CODE<?
Function run_code($code) {
If($code) {
ob_start();
eval($code);
$contents = ob_get_contents();
ob_end_clean();
}else {
echo "错误!没有输出";
exit();
}
return $contents;
}


以上这个例子的用途不是很大,不过很典型$code的本身就是一个含有变量的输出页面,而这个例子用eval把$code中的变量替换,然后对输出结果再进行输出捕捉,再一次的进行处理……

Example 6. 加快传输


CODE<?
/*
** Title.........: PHP4 HTTP Compression Speeds up the Web
** Version.......: 1.20
** Author........: catoc <catoc@163.net>
** Filename......: gzdoc.php
** Last changed..: 18/10/2000
** Requirments...: PHP4 >= 4.0.1
** PHP was configured with --with-zlib[=DIR]
** Notes.........: Dynamic Content Acceleration compresses
** the data transmission data on the fly
** code by sun jin hu (catoc) <catoc@163.net>
** Most newer browsers since 1998/1999 have
** been equipped to support the HTTP 1.1
** standard known as \"content-encoding.\"
** Essentially the browser indicates to the
** server that it can accept \"content encoding\"
** and if the server is capable it will then
** compress the data and transmit it. The
** browser decompresses it and then renders
** the page.
**
** Modified by John Lim (jlim@natsoft.com.my)
** based on ideas by Sandy McArthur, Jr
** Usage........:
** No space before the beginning of the first \'<?\' tag.
** ------------Start of file----------
** |<?
** | include(\'gzdoc.php\');
** |? >
** |<HTML>
** |... the page ...
** |</HTML>
** |<?
** | gzdocout();
** |? >
** -------------End of file-----------
*/
ob_start();
ob_implicit_flush(0);
function CheckCanGzip(){
global $HTTP_ACCEPT_ENCODING;
if (headers_sent() || connection_timeout() || connection_aborted()){
return 0;
}
if (strpos($HTTP_ACCEPT_ENCODING, \'x-gzip\') !== false) return \"x-gzip\";
if (strpos($HTTP_ACCEPT_ENCODING,\'gzip\') !== false) return \"gzip\";
return 0;
}
/* $level = compression level 0-9, 0=none, 9=max */
function GzDocOut($level=1,$debug=0){
$ENCODING = CheckCanGzip();
if ($ENCODING){
print \"n<!-- Use compress $ENCODING -->n\";
$Contents = ob_get_contents();
ob_end_clean();
if ($debug){
$s = \"<p>Not compress length: \".strlen($Contents);
$s .= \"
Compressed length: \".strlen(gzcompress($Contents,$level));
$Contents .= $s;
}
header(\"Content-Encoding: $ENCODING\");
print \"x1fx8bx08x00x00x00x00x00\";
$Size = strlen($Contents);
$Crc = crc32($Contents);
$Contents = gzcompress($Contents,$level);
$Contents = substr($Contents, 0, strlen($Contents) - 4);
print $Contents;
print pack(\'V\',$Crc);
print pack(\'V\',$Size);
exit;
}else{
ob_end_flush();
exit;
}
}
?>

这是catoc的一段很早以前的代码,是在weblogs.com看到的,他利用了zlib的函数,对传输的内容进行了压缩,测试表明,对于10k以上的页面,会产生效果,而且页面越大,效果越明显…
在我们使用查询语句的时候,经常要返回前几条或者中间某几行数据,这个时候怎么办呢?不用担心,mysql已经为我们提供了这样一个功能。
SELECT * FROM table  LIMIT [offset,] rows | rows OFFSET offset


LIMIT 子句可以被用于强制 SELECT 语句返回指定的记录数。LIMIT 接受一个或两个数字参数。参数必须是一个整数常量。如果给定两个参数,第一个参数指定第一个返回记录行的偏移量,第二个参数指定返回记录行的最大数目。初始记录行的偏移量是 0(而不是 1): 为了与 PostgreSQL 兼容,MySQL 也支持句法: LIMIT # OFFSET #。
mysql> SELECT * FROM table LIMIT 5,10;  // 检索记录行 6-15

//为了检索从某一个偏移量到记录集的结束所有的记录行,可以指定第二个参数为 -1:
mysql> SELECT * FROM table LIMIT 95,-1; // 检索记录行 96-last.

//如果只给定一个参数,它表示返回最大的记录行数目:
mysql> SELECT * FROM table LIMIT 5;     //检索前 5 个记录行

//换句话说,LIMIT n 等价于 LIMIT 0,n。

mysql> SELECT * FROM table LIMIT 95,-1; // 检索记录行 96-last.



                       $start = $offset * ($page-1);
                        $limit = $start.','.$offset;
                        $sql   = 'SELECT * FROM record '.$where.' ORDER BY ctime DESC LIMIT '.$limit;

大 多数人都知道爱迪生有句名言:天才是99%的汗水加上1%的灵感。今天在网上看到一篇文章,有人在文章的回复部分提到,爱迪生这句名言本身不是这样,是教 科书断章取义,爱迪生的原话因该是:天才是1%的灵感加上99%的汗水,但1%的灵感最重要,甚至比99%的汗水都重要。

很显然,如果加上后面的话,两种名言的版本表达的是完全不同的立场,但到底是不是这样呢?

随即到Google中查了一下,这篇文章:《中国教材:为什么要篡改爱迪生和爱因斯坦的名言?》可能是后一种名言版本的导火索,论证很充分,似乎是真的?但在这篇文章的评论处,有人以事实推翻了论证:

链接2: http://www.ortolon.com/articles_sterling_inspiration.htm
一开头便是这么写的:
“Inspiration and Perspiration
By Cindi Myers
Thomas Edison said, “Genius is one percent inspiration and ninety-nine percent perspiration.”
Without the one percent of inspiration, all the perspiration in the world is only a bucket of sweat….”

这后一段话翻译过来,跟原文所讲的那段加长版的名言非常贴切,想必应是原文理论之根据了。然而谁都不可能忽略的是:“没有1%的灵感,所有的汗水……”这句话并不在爱迪生名言的引号之内!

注意上面的标题
Inspiration and Perspiration
By Cindi Myers
已明确指出此文是Cindi Myers所写的一篇议论文。所以引号外的话不过是Cindi Myers的一句评价罢了。可惜口牙。

我想至此,考究结束,出处应该就是这里了。原文作者一开始便站在了错误的论据上。

不过,在我看来,论点却是好的……


该评论的作者摆出了事实,英文原句是否如他所说呢?随即到Google中搜索:Genius is one percent inspiration and ninety-nine percent perspiration,在出现的英文搜索结果中,几乎就是这句原话,没有所谓的“但1%的灵感最重要,甚至比99%的汗水都重要”的意思, 呵呵~~,在此可以确信,持第二种名言版本观点的人原来也有点断章取义了,教科书并没有更改爱迪生的名言。

说实话,当我看到第二种版本的时候,我有点信了,如果没有后面的确认,我可能还会给别人讲之前的爱迪生名言是错的,应该是什么什么等等。所以, 网上的信息应该有选择性地来吸收,不能见风是风,见雨是雨,即使是非常有“正义感”、感觉非常“权威”的那种,否则的话,只能是以讹传讹!

这个版本改进了不少地方,例如对ZF的良好支持。官方目前只提供法语、德语、意大利语三个语言包的下载,中文的还没有看到,再期待一下吧!

下载地址如下:

http://downloads.zend.com/studio-eclipse/6.0.1/ZendStudioForEclipse-6_0_1.exe (for windows)

http://downloads.zend.com/studio-eclipse/6.0.1/ZendStudioForEclipse-6_0_1.tar.gz (for linux)

http://downloads.zend.com/studio-eclipse/6.0.1/ZendStudioForEclipse-6.0.1.dmg (for mac,不好意思,一直不知道这个是MAC下的安装程序)

之前的注册机还可以继续使用,本人已测,呵呵~

KeyGen:http://www.niuc.net/attachment.php?fid=203


用户名:Faceker.com
注册码:02251FE3126660400000

用户名:PHPER
注册码:4784D9D0086669570000

可以到 Zend 官方网站下载 Zend Studio For Eclipse:[url=http://downloads.zend.com/studio-eclipse/6.0.0/ZendStudioForEclipse-6_0_0.zip]直接下载地址[/url]

我一直在寻找一个理想的 PHP 开发环境。之前一直用 Dreamweaver,但他只是一个完美的代码和 HTML 编辑器,在 PHP 开发方面,他连基本的自定义函数的参数都无法提示;有人推荐 EditPlus,不过他也只是个编辑器,离“开发环境”还差得远;再者就是 Zend Studio,他是公认的很好很强大的 PHP 开发环境,不过看到他那丑陋的界面,我就知道那不是我想要的。

后来知道了有个 PDT,基于 Eclipse 的 PHP 开发环境,用了一下,着实不错,界面也很美观,基本的 PHP 开发功能也够用,下定决心,从此就用他来搞 PHP 了。

过年期间,看到一条新闻,新版的 Zend Studio 发布了,该版本是基于 Eclipse 的开发环境,是在 PDT 的基础之上开发的,迫不及待地下载安装试用,WOW,一切都是那么的完美,毫无疑问,Zend Studio For Eclipse 将是以后 PHP 开发的不二选择了!


server.php:(UTF8编码)
<?php
// server
// 设置错误处理
error_reporting (e_all);
// 设置运行时间
set_time_limit (0);
// 起用缓冲
ob_implicit_flush ();
$ip = "127.0.0.1"; // ip地址
$port = 8848;  // 端口号
$socket = socket_create (AF_INET, SOCK_STREAM, SOL_TCP);  // 创建一个socket
if ($socket)
echo "socket_create() successed!\n";
else {
echo "socket_create() failed:".socket_strerror ($socket)."\n";
exit(0);
}

$bind = socket_bind ($socket, $ip, $port); // 绑定一个socket
if ($bind) {
  echo "socket_bind() successed!\n";
      }else{
        echo "socket_bind() failed:".socket_strerror ($bind)."\n";
        return 0;
       }

$listen = socket_listen ($socket);  // 间听socket
if ($listen)
echo "socket_listen() successed!\n";
else
echo "socket_listen() failed:".socket_strerror ($listen)."\n";

while (true)
{
$msg = socket_accept ($socket);  // 接受一个socket
if (!$msg)
{
echo "socket_accept() failed:".socket_strerror ($msg)."\n";
break;
}
$welcome0 = "welcome to php server!向东\n";
$welcome = iconv("utf-8","gbk",$welcome0);//显示gb的中文,否则在windows cmd 终端显示乱码
socket_write ($msg, $welcome, strlen ($welcome));
while (true)
{
$command = strtoupper (trim (socket_read ($msg, 1024)));
if (!$command)
break;
echo $command."\n";
switch ($command)
{
case "HELLO":
$writer = "hello everybody!";
break;
case "BYE":
$writer = "bye-bye";
break;
case "HELP":
$writer = "hello\tquit\thelp";
break;
default:
$writer = "error command!\n";
}
socket_write ($msg, $writer, strlen ($writer));
if ($command == "QUIT")
break;
}
socket_close ($msg);
}
socket_close ($socket);  // 关闭socket
?>
client.php(UTF8编码)
<?php
// Client
// 设置错误处理
error_reporting (E_ALL);
// 设置处理时间
set_time_limit (0);

$ip = "127.0.0.1";       // IP 地址
$port = 8848;            // 端口号

$socket = socket_create (AF_INET, SOCK_STREAM, SOL_TCP);   // 创建一个SOCKET
if ($socket)
    echo "socket_create() successed!/n";
else
    echo "socket_create() failed:".socket_strerror ($socket)."/n";

$conn = socket_connect ($socket, $ip, $port);       // 建立SOCKET的连接
if ($conn)
    echo "Success to connection![".$ip.":".$port."]/n";
else
    echo "socket_connect() failed:".socket_strerror ($conn)."/n";

echo socket_read ($socket, 1024);  

$stdin = fopen ('php://stdin', 'r');
while (true)
{
    $command = trim (fgets ($stdin, 1024));
    socket_write ($socket, $command, strlen ($command));
    $msg = trim (socket_read ($socket, 1024));
    echo $msg."\n";
    if ($msg == "Bye-Bye")
        break;
}
fclose ($stdin);
socket_close ($socket);
?>

1、 没有钱,没有权,再不对你好点,你能跟我?  

2、 买了电脑不上宽带,就好比酒肉都准备好了却在吃饭前当了和尚。  

3、天上掉钞票我不会弯腰,因为天上连馅饼都不会掉,更别说掉钞票了。  

4、 你给我买10条烟总比我去一次夜总会划算吧。  

5、要我扫地就绝对不刷碗,要我刷碗就绝对不扫地,两样一起做?你当我是外星人啊!  

6、 躺在床上看电视不如在看电视时上床睡觉。  

7、给我一个支点,我把邻居那小子的汽车翘到沟里去,省得他见我就按喇叭。  

8、参加选美的那些女人,都找不到好男人,因为好男人都结婚了,比如我。  

9、如果领导下个月再不给我加薪,我就辞职,辞职前再给他送两条中华,抽死他。  

10、 如果猪都会飞了,谁还买飞机?骑着猪上天不就行了。  

11、 我的领带又找不到了,是不是你昨天又没有找到抹布?  

12、 在埃及,一个男人可以娶四个老婆,那得多累啊,还是中国好。  

13、 你还是让我跪搓板吧,跪电暖气实在受不了啊!  

14、 我就算是一只癞蛤蟆,我也决不娶母癞蛤蟆。  

15、 喝白酒一斤,我绝对没感觉,因为喝半斤就已经喝死了。  

16、上厕所看报纸等同于大便完了擦屁股,是一个流程,否则不叫完工。  

17、儿子不听话可以适当的打打,要不就显不出老子的威严,台-湾问题就是如此。  

18、我妈过生日,送脑白金还不如送两块大梁骨煮煮吃,至少还能当下酒菜。  

19、 我才不去见网友,除非国家修改一夫一妻制。  

20、 下辈子我还找你,因为除了我,你是最傻的
1.由于50上的qmail不需要验证就可以发信,有了验证反而出现错误,最后在133那台机器就可以了,auth login afeng133@afeng133.sina.net 123qwe(Base64),然后给126(xxx108@126.com)发了信可以收到,不错不错,以下文件存为utf8 格式:

如果有获取whoami之类的,修改配置文件 php.ini 把exec的执行权限放开!

smtp.class.php:

<?php
set_time_limit(120);
class smtp_mail
{
    var $host="";          //主机
    var $port="25";          //端口 一般为25
    var $user="";          //SMTP认证的帐号
    var $pass="";          //认证密码
    var $debug = false;   //是否显示和服务器会话信息?
    var $conn;
    var $socket="";
    var $result_str;      //结果
    var $in;          //客户机发送的命令
    var $from_r;          //真实的源信箱,一般与smtp服务器的用户名一样,否则可能由于smtp服务器的设置而发送不成功
    var $mailformat=0; //邮件格式 0=普通文本 1=html邮件

    function smtp_mail($host,$port,$user,$pass,$debug=false)
    {
        $this->host  = $host;
        $this->port   = $port;
        $this->user   = base64_encode($user);
        $this->pass   = base64_encode($pass);
        $this->debug  = $debug;
        $this->socket = socket_create (AF_INET, SOCK_STREAM, SOL_TCP);  //具体用法请参考手册
        if($this->socket)
        {
              //$this->result_str  =  "创建SOCKET:".socket_strerror(socket_last_error());
              $this->result_str  =  "创建SOCKET:".iconv("GBK","UTF-8//TRANSLIT//IGNORE", socket_strerror(socket_last_error()));
              $this->debug_show($this->result_str);
        }
        else
        {
            exit("初始化失败,请检查您的网络连接和参数");
        }
        $this->conn = socket_connect($this->socket,$this->host,$this->port);
        if($this->conn)
        {
            $this->result_str  =  "创建SOCKET连接:".iconv("GBK","UTF-8//TRANSLIT//IGNORE",socket_strerror(socket_last_error()));
            $this->debug_show($this->result_str);
        }
        else
        {
            exit("初始化失败,请检查您的网络连接和参数");
        }
        $this->result_str = "服务器应答:<font color=#cc0000>".socket_read ($this->socket, 1024)."</font>";
        $this->debug_show($this->result_str);
    }

    function debug_show($str)
    {
        if($this->debug)
        {
            echo $str."<p>\r\n";
        }
    }

    function send($from,$to,$subject,$body)
    {
        if($from == "" || $to == "")
        {
            exit("请输入信箱地址");
        }
        if($subject == "") $sebject = "无标题";
        if($body    == "") $body    = "无内容";

        $All          = "From:".$from."\r\n";
        $All          .= "To:".$to."\r\n";
        $All          .= "Subject:".$subject."\r\n";
        if($this->mailformat==1) $All.= "Content-Type: text/html;\r\n";
        else $All .= "Content-Type: text/plain;\r\n";
        $All          .= "charset=gb2312\r\n\r\n";
        $All          .= $body;
        /*
          如果把$All的内容再加处理,就可以实现发送MIME邮件了
          不过还需要加很多程序
        */

        //以下是和服务器会话
        $this->in       =  "EHLO HELO\r\n";
        $this->docommand();

        $this->in       =  "AUTH LOGIN\r\n";
        $this->docommand();
        $this->in       =  $this->user."\r\n";

        $this->docommand();

        $this->in       =  $this->pass."\r\n";
        $this->docommand();

        if(!eregi("235",$this->result_str)){
           $this->result_str = "smtp 认证失败";
           $this->debug_show($this->result_str);
           return 0;
        }

        $this->in       =  "MAIL FROM:<".$from.">\r\n";
        $this->docommand();

        $this->in       =  "RCPT TO:<".$to.">\r\n";
        $this->docommand();

        $this->in       =  "DATA\r\n";
        $this->docommand();

        $this->in       =  $All."\r\n.\r\n";
        $this->docommand();

        if(!eregi("250",$this->result_str)){
           $this->result_str = "邮件发送失败";
           $this->debug_show($this->result_str);
           return 0;
        }

        $this->in       =  "QUIT\r\n";
        $this->docommand();

        //结束,关闭连接
        return 1;
    }

    function docommand()
    {
        socket_write ($this->socket, $this->in, strlen ($this->in));
        //$this->debug_show("客户机命令:".iconv("GBK","UTF-8", $this->in));
        $this->debug_show("客户机命令:".iconv("GBK","utf-8//TRANSLIT//IGNORE", $this->in)); //防止报错:Notice: iconv(): Unknown error (84)
        $this->result_str = "服务器应答:<font color=#cc0000>".iconv("GBK","UTF-8//TRANSLIT//IGNORE", socket_read ($this->socket, 1024))."</font>";
        $this->debug_show($this->result_str);
    }

} //end class
?>

sendmail.php:

<?php
  header("Content-type: text/html; charset=utf-8");
?>
<?php
  include("smtp.class.php");
  //$mails=new smtp_mail("220.181.15.111","25","xxx108@126.com","********");
  $mails=new smtp_mail("220.181.15.111","25","xxx108@126.com","********",true);
  $date = date("Y-m-d H:i:s");
  if($mails->send("xxx108@126.com","xxx108@126.com","有人于".$date."登录服务器","请注意是否自己在该时间登录。","登录时间。"))
  {
    echo "发送成功!";
  }else{
      echo "邮件服务器忙,请稍候再试试";
  }
?>


如果有获取谁的exec函数加上(修改配置文件 php.ini 把exec的执行权限放开!):

这个程序的实质是模仿如下终端操作:

telnet smtp.sina.net 25
Trying 202.108.37.33...
Connected to smtp.sina.net.
Escape character is '^]'.
220 sina3-197.sina.net ESMTP - qmail-1.04
helo sina.net
250 sina3-197.sina.net
AUTH LOGIN
334 VXNlcm5hbWU6
ZWFzdHN1bkBlYXN0c3VuLnNpbmEubmV0
334 UGFzc3dvcmQ6
MTIzcXdl
235 验证通过- authentication successfully
data
503 请先用 RCPT - RCPT first (#5.5.1)
mail from:<xxx108@126.com>
250 Mail OK
rcpt to:<xxx108@126.com>  
rcpt to:<372647693@qq.com>      //第二个抄送人
250 Mail OK
data
354 End data with <CR><LF>.<CR><LF>
From: Mail test <372647693@qq.com>
Sender: jackxiang <xxx108@126.com>
To: xxx108@126.com
Cc: 372647693@qq.com
Subject: mail testing mail title

This is mail content...

.
250 Mail OK queued as smtp1,C8mowEDpO0uNr0dUwfhiAA--.1433S3 1413984769

(最后这个小数点一定要加上)

此时,372647693@qq.com也会收到,这个cc:就是抄送人,在邮件标题里体现,真正发还是在rcpt to:<372647693@qq.com>      //第二个抄送人。

邮件标题:
mail testing mail title
发件人:Mail test<372647693@qq.com> (由 xxx108@126.com 代发)
收件人:我<xxx108@126.com>
抄送人:372647693<372647693@qq.com>
This is mail content...

QQ邮箱:
发件人:我自己的邮箱 <372647693@qq.com>(由 xxx108@126.com 代发)
时   间:2014年10月22日(星期三) 晚上9:46  
收件人:xdy108 <xxx108@126.com>
抄   送:回忆未来-向东-Jàck <372647693@qq.com>
This is mail content...

————————————————————————————————————————————————————————
以下如果打开$mails=new smtp_mail("smtp.sina.net","25","eastsun@eastsun.sina.net","123qwe","false");  //false
可以看见其到底是如何进行会话的,如下:
创建SOCKET:您的主机中的软件放弃了一个已建立的连接。
创建SOCKET连接:您的主机中的软件放弃了一个已建立的连接。

服务器应答:220 smtp-5-32.sina.net ESMTP - qmail-1.04

客户机命令:EHLO HELO

服务器应答:250-smtp-5-32.sina.net 250-AUTH=LOGIN 250-AUTH LOGIN 250-PIPELININGJH 250 8BITMIME

客户机命令:AUTH LOGIN

服务器应答:334 VXNlcm5hbWU6

客户机命令:ZWFzdHN1bkBlYXN0c3VuLnNpbmEubmV0

服务器应答:334 UGFzc3dvcmQ6

客户机命令:MTIzcXdl

服务器应答:235 验证通过 - authentication successfully

客户机命令:MAIL FROM:xiaoqian@staff.sina.com.cn

服务器应答:250 eastsun@eastsun.sina.netok

客户机命令:RCPT TO:xiangdong2@staff.sina.com.cn

服务器应答:250 ok

客户机命令:DATA

服务器应答:354 请继续 - go ahead

客户机命令:From:xiaoqian@staff.sina.com.cn To:xiangdong2@staff.sina.com.cn Subject:我来个中文测试一下,怎么就不正常了呢,哈哈。。向东 Content-Type: text/plain; charset=gb2312 我来个中文测试一下,这里是信的内容!!! .

服务器应答:250 ok 1212053255 qp 74366

客户机命令:QUIT

服务器应答:221 smtp-5-32.sina.net

发送成功!


对用户名和密码的Base64编码方法:

<?php
$user="xiangdong2@staff.sina.com.cn";          
$pass="xiangdong";
$user   = base64_encode($user);
$pass   = base64_encode($pass);
echo $user."\n";
echo $pass."\n";
?>




[root@vm0000055 ~]# telnet staff.sina.com.cn 110
Trying 10.210.98.10...
Connected to staff.sina.com.cn (10.210.98.10).
Escape character is '^]'.
+OK staff-jes1.sina.com.cn POP3 service (Sun Java(tm) System Messaging Server 6.2-3.04 (built Jul 15 2005))
xiangdong2
-ERR Unrecognized command
xiangdong2@staff.sina.com.cn
-ERR Unrecognized command
USER xiangdong2
+OK Name is a valid mailbox
pass xiangdong  
+OK Maildrop ready
AUTH
-ERR Unrecognized command
LIST
+OK scan listing follows
1 1675
2 8490
3 3004
4 625
5 650
6 1877
7 1928
8 1939
9 2131
.
RETR 1
+OK 1675 octets
Return-path: <jinsong@staff.sina.com.cn>
Received: from sina123123123 ([10.218.26.58]) by staff-jes1.sina.com.cn
(Sun Java System Messaging Server 6.2-3.04 (built Jul 15 2005))
id <0KLS00I01MFE7V00@staff-jes1.sina.com.cn>
(original mail from jinsong@staff.sina.com.cn); Thu,
25 Jun 2009 20:01:15 +0800 (CST)
Received: from sina123123123 ([10.218.26.58]) by staff-jes1.sina.com.cn
(Sun Java System Messaging Server 6.2-3.04 (built Jul 15 2005))
with ESMTPA id <0KLS00OCGMQ2Q1B0@staff-jes1.sina.com.cn>; Thu,
25 Jun 2009 20:01:14 +0800 (CST)
Date: Thu, 25 Jun 2009 20:01:34 +0800
From: =?GB2312?B?wbq+osvJ?= <jinsong@staff.sina.com.cn>
Subject:
=?gb2312?B?vfHM7M/Czuc2o7owMLnHuMnN+LnK1c+jrNbQtefQxbPGueO2q7P2yqHCt9PJxvez9rnK1c8g1OyzybulwarN+NO1yPs=?=
To: cpyw <cpyw@staff.sina.com.cn>, sinamail <sinamail@staff.sina.com.cn>,
platform <platform@staff.sina.com.cn>
Message-id: <200906252001339840407@staff.sina.com.cn>
MIME-version: 1.0
X-Mailer: Foxmail 6, 9, 201, 16 [cn]
Content-type: text/plain; charset=gb2312
Content-transfer-encoding: base64

vfHM7M/Czuc2o7owMLnHuMnN+LnK1c+jrNbQtefQxbPGueO2q7P2yqHCt9PJxvez9rnK1c8g1Oyz
ybulwarN+NO1yPsNCmh0dHA6Ly90ZWNoLnNpbmEuY29tLmNuL3QvMjAwOS0wNi0yNS8xOTMyMzIx
MjIyNS5zaHRtbA0KaHR0cDovL3RlY2guc2luYS5jb20uY24vdC8yMDA5LTA2LTI1LzE5MTYzMjEy
MjEzLnNodG1sDQpodHRwOi8vdGVjaC5zaW5hLmNvbS5jbi9pLzIwMDktMDYtMjUvMTkyNTMyMTIy
MTguc2h0bWwNCiAJCQkJDQotLS0tLS0tLS0tLS0tLQ0Kwbq+osvJDQoNCnNpbmG7pbavyefH+NTL
06rWp7PW1+kNCg0Ktee7sKO6MDEwo602MjY3NjgxMQ0KDQrK1rv6o7oxMzcxNzkwMzMxOQ0KDQrT
ys/ko7pqaW5zb25nQHN0YWZmLnNpbmEuY29tLmNuIA0KDQpNU046cm9zZWxpYW5nanNAaG90bWFp
bC5jb20NCg0KUVE6NjQyNzkyMjI0DQoyMDA5LTA2LTI1DQo=








PHP通过Socket来发送网页Post请求和Get请求Ok代码:

如果没有Host在里面[fwrite($sock, "Host: upload.com\r\n");],则会出现:
51 [Mon Jun 20 18:12:19 2011] [error] [client 172.25.38.70] client sent HTTP/1.1 request without hostname (see RFC2616
        section 14.23): /upload/upload.cgi


判断refer啥的,这块涉及到php的curl传refer,请参考:
伪造refer:  https://jackxiang.com/post/4022/
伪造Host绑定来源:https://jackxiang.com/post/4423/
明天结婚。是阿里巴巴集团同事的集体婚礼。

和老婆风风雨雨一路走来。大学最后一年相识,毕业后,她在青岛,我在北京。她抛弃很好的工作背景,杀到北京,在北京生活三年,又和我一起来到杭州发展。感激老婆,每次虽然面对的不是什么大决择,也需要很大的勇气,想起来多不容易。这期间尤其令我感到内疚的是在北京期间老婆压力过大导致生病,深深自责。

不管怎么样,祝福我们吧! 我先祝福一下 :)

冯大辉(David Feng)

大学的专业是生物技术,毕业后从事计算机行业。

在 IT 行业的这几年基本上是做 Oracle 数据库相关的技术工作,对 Oracle 数据库的管理与性能优化有一点研究,有点实践经验,乐于分享技术经验,是一名 Oracle ACE (bio,中文介绍)。我的技术背景包括:



Oracle RDBMS
Unix / Linux
Web / Security


曾经参与编辑两本 Oracle 的技术图书:



《Oracle数据库性能优化》
《Oracle数据库DBA专题技术精粹》


此外曾参与翻译过三本计算机图书。

现就职于阿里巴巴集团旗下支付宝(中国)网络技术有限公司。任职数据库架构师 。

这个站点是我实验 Web 技术与知识积累的场所,秉承"最简约的技术取得最大的收益"的理念,希望也能对其他人有点用。如您所知,本人发布的文章与评论内容仅代表本人观点。一般在网上我用 "Fenng" 这个ID 进行技术交流。

我是东北人,现在生活在杭州。养了两只猫. 喜欢 The Cure 的音乐.

可以通过网络电话或者电子邮件和我联系: dbanotes@gmail.com

  function set_upload_data($arr_upload)
  {
    $this->attachment=$arr_upload[files];
    $this->upload_dir=$arr_upload["upload_dir"];
    
  }
  function uploadfile()
  {  
    $fileName = mb_convert_encoding($this->attachment['name'],'GBK','UTF-8');//这一行开始转码,否则出现乱码
   //$fileName = iconv("UTF-8","GBK", $this->attachment['name']);  //这样也行,由UTF-8转到GBK,和上面的函数有区别
    if(move_uploaded_file($this->attachment['tmp_name'],$this->upload_dir.$fileName))
    {  
      return 1;//上传成功
  
    }else{  
        return 0;//上传失败
        }
  }

参考如下文章:
mb_convert_encoding这个函数是用来转换编码的。原来一直对程序编码这一概念不理解,不过现在好像有点开窍了。
不过英文一般不会存在编码问题,只有中文数据才会有这个问题。比如你用Zend Studio或Editplus写程序时,用的是gbk编码,如果数据需要入数据库,而数据库的编码为utf8时,这时就要把数据进行编码转换,不然进到数据库就会变成乱码。

mb_convert_encoding的用法见官方:
http://cn.php.net/manual/zh/function.mb-convert-encoding.php

做一个GBK To UTF-8
< ?php
header("content-Type: text/html; charset=Utf-8");
echo mb_convert_encoding("妳係我的友仔", "UTF-8", "GBK");
?>

再来个GB2312 To Big5
< ?php
header("content-Type: text/html; charset=big5");
echo mb_convert_encoding("你是我的朋友", "big5", "GB2312");
?>
不过要使用上面的函数需要安装但是需要先enable mbstring 扩展库。

PHP中的另外一个函数iconv也是用来转换字符串编码的,与上函数功能相似。

下面还有一些详细的例子:
iconv — Convert string to requested character encoding
(PHP 4 >= 4.0.5, PHP 5)
mb_convert_encoding — Convert character encoding
(PHP 4 >= 4.0.6, PHP 5)

用法:
string mb_convert_encoding ( string str, string to_encoding [, mixed from_encoding] )
需要先enable mbstring 扩展库,在 php.ini里将; extension=php_mbstring.dll 前面的 ; 去掉
mb_convert_encoding 可以指定多种输入编码,它会根据内容自动识别,但是执行效率比iconv差太多;


string iconv ( string in_charset, string out_charset, string str )
注意:第二个参数,除了可以指定要转化到的编码以外,还可以增加两个后缀://TRANSLIT 和 //IGNORE,其中 //TRANSLIT 会自动将不能直接转化的字符变成一个或多个近似的字符,//IGNORE 会忽略掉不能转化的字符,而默认效果是从第一个非法字符截断。
Returns the converted string or FALSE on failure.


使用:

发现iconv在转换字符”—”到gb2312时会出错,如果没有ignore参数,所有该字符后面的字符串都无法被保存。不管怎么样,这个”—”都无法转换成功,无法输出。 另外mb_convert_encoding没有这个bug.

一般情况下用 iconv,只有当遇到无法确定原编码是何种编码,或者iconv转化后无法正常显示时才用mb_convert_encoding 函数.

from_encoding is specified by character code name before conversion. it can be array or string - comma separated enumerated list. If it is not specified, the internal encoding will be used.
/* Auto detect encoding from JIS, eucjp-win, sjis-win, then convert str to UCS-2LE */
$str = mb_convert_encoding($str, “UCS-2LE”, “JIS, eucjp-win, sjis-win”);
/* “auto” is expanded to “ASCII,JIS,UTF-8,EUC-JP,SJIS” */
$str = mb_convert_encoding($str, “EUC-JP”, “auto”);

例子:
$content = iconv(”GBK”, “UTF-8″, $content);
$content = mb_convert_encoding($content, “UTF-8″, “GBK”);

如果前端是GBK,而在生成Json时需要做转换才能中文正常显示,如下(把GBK转为Utf8):

最后:Ajax走的都是Utf8,所以得从GBK转为Utf8.
PHP的主要语言开发者之一、Zend公司的创始人之一Andi Gutmans最近在blog中直言不讳地批评了Java语言。他指出,目前Java厂商试图在JVM上提供动态语言实现的路子根本不对,Java已经输掉了Web开发语言的战争,PHP是事实上的标准和胜利者。

Gutmans的这篇文章在技术界引发了强烈争议,很对人对此有不同的意见,我在这里就阐述一下我对PHP和Java两种语言的看法。

我早先曾经在《Perl、PHP、ASP、JSP技术比较》一文中对比过PHP和Java的异同,简而言之,PHP是一种解释执行的脚本语言,语法和C语言类似,易学易用,不懂电脑的非专业人员稍经学习也能使用PHP.而Java要先编译成Class文件,然后在Java虚拟机上执行,Java开发需要熟悉Java语法以及一些核心的架构,从而实现一种可复用的、跨平台的软件,Java比PHP要难学的多。

实际上,从技术架构来说,Java语言相比PHP有明显的优势,Java使用的是面向对象的系统设计方法,而PHP还是采用面向过程的开发方法。PHP只能实现简单的分布式两层或三层的架构,而JAVA可以实现多层架构。数据库层(持久化层)、应用(业务)逻辑层、表示逻辑层彼此分开,而且现在不同的层都已经有一些成熟的开发框架的支持。例如Struts就是利用Java的web开发技术实现了MVC的设计模式,而在业务逻辑层也有Spring框架,数据库持久化层有Hibernate等框架。这些框架可以方便开发者高效、合理、科学得架构多层的商业应用。从数学运算和数据库访问速度来讲,Java的性能也优于PHP.实际上,对于跨平台的大型的企业应用系统来讲,Java几乎已经成为唯一的选择(微软.NET不支持跨平台),但是在于Web网站应用开发来讲,Java却面临着被PHP边缘化的危险,几乎所有的虚拟主机都支持PHP+MySQL,而支持Java的却少之又少,在资源上,网上有不计其数的PHP资源,很多著名的大型网站(例如Facebook、Mediawiki等)都是基于PHP的,而成功的Java网站却寥寥无几,这又是什么原因呢?

Java的理念是“一次编写,到处运行”,Java在应用框架底下的架构是无与伦比的,远胜过其他任何语言,Java的框架利于大型的协同编程开发,系统易维护、可复用性较好。而PHP很容易自学,让热备能快速简洁地编写代码,适合于快速开发,中小型应用系统,开发成本低。在调试、发布上,PHP也较Java简单。

理念上的不同导致了Java和PHP在Web应用开发上显示了不同的结果,尽管Java的数学计算和数据库访问都有优势,架构也相当完美,但是PHP却可以简单轻松地支持高强度Web访问,能够快速开发应用,支持PHP的虚拟主机多如牛毛,使得用PHP开发一个网站比用Java开发一个网站要快得多,容易的多。Java所拥有的优点只适合传统的以软件项目为核心的开发模式,而PHP更适合于以客户为核心的SaaS的开发模式,因此,PHP目前在Web网站开发的优势完全是因为Web网站开发的特殊性而导致的,并非编程语言特性所决定。

因此,PHP在Web网站开发语言的战争中已经慢慢将Java抛在了后面,Java要想在Web网站开发上奋起直追,的确应该多听听Andi Gutmans的意见,彻底改变一下思路才行,否则两者的差距只能是越来越远。

另外,虽然在国际上LAMP(Linux+Apache+Mysql+Php)架构已经占领了统治地位,但是在中国国内还有一个怪胎,就是基于微软的Windows Server+IIS+SqlServer+ASP/ASP.NET的架构,从理论上说,微软的这一套架构也能实现不错的性能,只可惜Windows和SqlServer价格不菲,整个架构在性能上比起LAMP不仅没有什么优势,反而还有不少劣势,因此微软的这一套家伙在国际市场上吃不开。而国内使用微软盗版则可以忽略成本,而ASP的易学易用性不逊于PHP,甚至连IT外行都能够使用,因此在国内也有不小的市场。但是随着中国在保护知识产权方面的日趋完善,免费的LAMP依旧是未来的趋势。
人的一生,分为童年,少年,青年,中年,老年五个阶段。
   童年是个迷,混沌初开,诸事未晓,一切惟凭本能,感性用事,他对世界,外人对于他,均不甚了了,是个“迷”。少年是一幅画,初具理性,乍识人生,但童心未泯,天真浪漫,恰如多姿多彩“一幅画”。青年是一首诗,情窦初开,英姿勃发,潇洒浪漫。对爱情,事业,前程充满憧憬,是为“一首诗”。中年是一篇散文,人到中年,曾经沧海难为水,除却巫山不是云,这时,对人生,社会,现实已有相当的阅历,回首往事,展望未来,谁无万千感慨?这时涉世更深,对人生的理解又上一层楼,多了几分飘逸,此时宛如“一篇散文”。老年是一套哲学,老之已至,两鬓飞霜,悟透人生,深知天命。无为者,因悲黄泉路近,老气横秋,哀叹“转眼八旬已到,回头万事皆空”。有为者,自觉来日无多,老当益壮,高歌“满目清山夕阳照”,到达这种境界,无论是前者还是后者,都是“一套哲学”。
    这就是人生的五个阶段,在这五个阶段里,男人和女人又有所不同。有说女人是水,男人是泥,女人是船,男人是舵,船没有舵手不行,女人没男人不成事。不然,女人细腻,男人粗犷,所以,女人在选择男人靠知觉,男人选择女人凭感觉。男人爱用眼睛看女人,最容易受美丽的诱惑,女人爱用心去想男人,最容易受心的折磨,在聪明和美貌之间,男人则往往看重美貌,男人爱看女人眼前怎样,女人爱看男人今后如何。
    孩童时,男孩看女孩是雾里看花,不明所以,只会眼晴发亮,女孩看男孩是水中观月,只凭自己的喜恶
    青少年时,男人说世上值得爱的女人不止一个,女人却说世上值得爱的只有一个,男人找女人时很少精心思索,女人找男人时苦心琢磨,对女人来说,一辈了听不烦的话是-我爱你;对男人来说-辈子想不完的是-我爱谁。
    中年时,男人的美,美在深度和真诚,女人的美,美在风度和表情,男人说,世间的美,是因为有男人对女人的爱,女人说,女人给世界的爱才产生一切的美。女人是二十而美,三十而强,四十而贤,五十而润,六十而精。男人对女人应是二十而慕,三十而助,四十而敬,五十而赏,六十而伴。
    到了老年,男人说做男人难,要生命不息,奋斗不止,像拉满的弓和不能回头的箭;女人说做女人难,做女强人要受责难,退而守家,保家,又是目光短浅。
    于是,男人和女人时常想换位置,但是,如果换了位置又如何呢?还不如选择少年夫妻老来伴,执子之手,与子偕老的平淡生活。共同走好人生的五个阶段。
Windows Media Player文件

Let's dance in style,
Let's dance for a while
Heaven can wait,
We're only watching the skies
Hoping for the best
But expecting the worst
Are you going to drop the bomb or not????
Let us die young or let us live forever
We don't have the power
But we never say never
Sitting in a sandpit,
Life is a short trip
The music's for the sad men
Can you imagine when this race is won??
Turn our golden faces into the sun
Praising our leaders,
We're getting in tune
The music's played by the madmen

Forever young, I want to be forever young
Do you really want to live forever
Forever -- and ever

Some are like water
Some are like the heat
Some are a melody and some are the beat
Sooner or later, they all will be gone
Why don't they stay young?
It's so hard to get old without a cause
I don't want to perish like a fading horse
Youth's like diamonds in the sun
And diamonds are forever
So many adventures couldn't happen today
So many songs we forgot to play
So many dreams swinging out of the blue
We'll let them come true
Windows Media Player文件


whole life the wonder such you bring the beauty
i can see but i keep deep inside on it
oh life i feel that i can bring it again
in the world where love will still remain

choose your words make them whys
many things have produced(?) where we are
i am here
here with you
close your eyes let love heal the sorrow
once again i feel in life
i'm sure of this insight
and i need you more than ever
life's told me so much more
feel stronger than before of this feeling stay here forever
long ago i was blind
i thought the love was so waste here to stay
but we walked all the way
and we said good bye
even though i knew i loved you still
suddenly you were gone and she was in your rounds
its picture i remember
i was lost could not be saved my life just ran away
i only wish that we could start over
but true love will find its way
now i love it seemed to stay
i lost it once and now i found the way to live again

oh life i wonder such you bring the beauty
i can see but i keep deep inside on it
oh life i feel that i can bring it again
in the world where love will still remain

but true love will find its way
now i love it seemed to stay
i lost it once now i found the way to live again

oh life the wonder such you bring the beauty
i can see but i keep deep inside on it
oh life i feel that i can bring it again
in the world where love will still remain
mmm....
in the world where love will still remain

汗!

生活笔记 jack 2008-5-27 17:58
 一只小鸟正在飞往南方过冬的途中。天气太冷了,小鸟冻僵了,从天上掉下来,跌在一大片农田里。它躺在田里的时候,一只母牛走了过来,而且拉了一泡屎在它身上。冻僵的小鸟躺在牛屎堆里,发掘牛粪真是太温暖了。牛粪让它慢慢缓过劲儿来了!它躺在那儿,又暖和又开心,不久就开始高兴地唱起歌来了。一只路过的猫听到了小鸟的歌声,走过来查个究竟。顺着声音,猫发现了躲在牛粪中的小鸟,非常敏捷地将它刨了出来,并将它给吃了!

  这个故事的寓意是……

  1) 不是每个在你身上拉屎的都是你的敌人。

  2) 不是每个把你从屎堆中拉出来的都是你的朋友。

  3) 而且,当你陷入深深的屎堆当中(身陷困境)的时候,闭上你的鸟嘴!
背景:有哥们在一PHP群里发现另一个哥们设置cookie的代码编写有点意思,如下:
[codes=php]
$cookieJson = json_encode($cookieArr);
$_COOKIE['userInfo'.$this->roteId] = $cookieJson;
setcookie('userInfo'.$this->roteId,$cookieJson );
[/codes]
阅读全文
http协议是一种无状态的连接,要想跟踪用户的行为就必须有一个能工作于不同于页面的变量,在PHP中可以用cookie和session两种办法实现。
cookie大家比较熟悉了,就是在把变量存为客户端上的一个文件而已,但是如果客户禁止cookie就没办法了。这就需要session了,在PHP4 中,session可以有两种办法实现,一是用cookie,即把sessionID保存在cookie文件中;二是把sessionID附带在URL上进行传递。
虽有这两种办法实现,但至于使用哪种方法是不用程序员操心的,PHP会自动检查客户cookie的设置的(指linux/unix平台,Win32未知),并且默认的是优先使用cookie(你可以修改php.ini文件中的[session]一节的session.use_cookies的值来改变)。当然你也可以强制使用URL来传递SessionID,如下:
<a href="submit.php<?=sessionID;?>">提交表单</a>
仅在链接中加一句<?=sessionID;?>就行了,简单吧?在php.ini中还有许多关于Session的设置,如 session.cookie_lifetime是session的有效时间等,都在[session]一节中,若看看的话会对PHP中的session 有更多的理解的。
   具体来说cookie机制采用的是在客户端保持状态的方案,而session机制采用的是在服务器端保持状态的方案。同时我们也看到,由于采用服务器端保持状态的方案在客户端也需要保存一个标识,所以session机制可能需要借助于cookie机制来达到保存标识的目的,但实际上它还有其他选择。

     cookie机制。正统的cookie分发是通过扩展HTTP协议来实现的,服务器通过在HTTP的响应头中加上一行特殊的指示以提示浏览器按照指示生成相应的cookie。然而纯粹的客户端脚本如JavaScript或者VBScript也可以生成cookie。而cookie的使用是由浏览器按照一定的原则在后台自动发送给服务器的。浏览器检查所有存储的cookie,如果某个cookie所声明的作用范围大于等于将要请求的资源所在的位置,则把该 cookie附在请求资源的HTTP请求头上发送给服务器。
     cookie的内容主要包括:名字,值,过期时间,路径和域。路径与域一起构成cookie的作用范围。若不设置过期时间,则表示这个cookie的生命期为浏览器会话期间,关闭浏览器窗口,cookie就消失。这种生命期为浏览器会话期的cookie被称为会话cookie。会话cookie一般不存储在硬盘上而是保存在内存里,当然这种行为并不是规范规定的。若设置了过期时间,浏览器就会把cookie保存到硬盘上,关闭后再次打开浏览器,这些 cookie仍然有效直到超过设定的过期时间。存储在硬盘上的cookie可以在不同的浏览器进程间共享,比如两个IE窗口。而对于保存在内存里的 cookie,不同的浏览器有不同的处理方式
     session机制。session机制是一种服务器端的机制,服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存信息。
  
     当程序需要为某个客户端的请求创建一个session时,服务器首先检查这个客户端的请求里是否已包含了一个session标识(称为session id),如果已包含则说明以前已经为此客户端创建过session,服务器就按照session id把这个session检索出来使用(检索不到,会新建一个),如果客户端请求不包含session id,则为此客户端创建一个session并且生成一个与此session相关联的session id,session id的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串,这个session id将被在本次响应中返回给客户端保存。
     保存这个session id的方式可以采用cookie,这样在交互过程中浏览器可以自动的按照规则把这个标识发挥给服务器。一般这个cookie的名字都是类似于 SEEESIONID。但cookie可以被人为的禁止,则必须有其他机制以便在cookie被禁止时仍然能够把session id传递回服务器。
     经常被使用的一种技术叫做URL重写,就是把session id直接附加在URL路径的后面。还有一种技术叫做表单隐藏字段。就是服务器会自动修改表单,添加一个隐藏字段,以便在表单提交时能够把session id传递回服务器。比如:
      <form name="testform" action="/xxx">
      <input type="hidden" name="jsessionid" value="ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764">
      <input type="text">
      </form>
实际上这种技术可以简单的用对action应用URL重写来代替。

在一个页面设置一个cookie时,必须刷新或到下一个页面才可以用 $_COOKIE 得到变量的值.

原因是因为当页面第一次被浏览器访问载入时,页面中的 cookie 会被设置,将其发送存储到客户端指定的

存储位置,所以$_COOKIE没有接收到客户端发送过来的 cookie 变量的值,当刷新或到下一个页面时,客户

端会在页面程序在服务器端运行之前,发送与该地址相对应的 cookie到服务器端,所以 $_COOKIE 可以得

到的值!
说白了就是当每一个页面被访问时,如果客户端找到了与访问地址相对应的 cookie 时,会在程序在服务器

端运行之前发送这个 cookie 到服务器端. (个人对此的看法)

本人表达能力不强,如有不明,还请抱歉!

php中设置cookie数组的时候,不可以用像php中的那个添加数据的方法:
<?php
setcookie('my_cookie[]', 1);
setcookie('my_cookie[]', 2);
print_r($_COOKIE);    // Array ( [my_cookie] => Array ( [0] => 1 ))
                      // 数组的值添加是添加成功了,不过索引没有变,后面的数据将前的数据覆盖了!

由此得到
       my_cookie[],默认指向数据的第一元素的位置,即索引为

0 的位置. 注意与php中的不一样! 以后用cookie数据记住要指定数组元素索引哦!
      
$my_cookie[] = 1;
$my_cookie[] = 2;
print_r($my_cookie); //Array ( [0] => 1 [1] => 2)
?>

删除 cookie 变量的两个方法:
1.php
<?php
setcookie('user_name_1', 'zhaofei299', time()+3600); // 生存期为 1 个小时
setcookie('user_name_2', 'ZHAOFEI299', time()+3600); // 生存期为 1 个小时
?>

2.php
<?php
setcookie('user_name_1');                // 第一种              
setcookie('user_name_2', "", time()-1); // 第二种
print_r($_COOKIE);                       // 刷新页面2下以上会输出 Array ( [user_name_1] => )

/*为什么超级全局变量 $_COOKIE 中的 user_name_1 没有被删除(变量为空并不代表不存在),而

user_name_2被删除了? 那是因为两个删除变量的方式不同!

第一种: 是设置了 cookie 的生存期, 只不过是将它的值默认设置为空,生存期为与浏览器一样,浏览器

关闭时,cookie才会删除!所以当重新打开一个浏览器,输出地址时,才会发现 cookie 变量全部被删除了!

将2.php 中两个 setcookie() 函数部分注释掉看看(重新输出了地址)!

第二种: 也是设置了 cookie 的生存期,是使 cookie 的生存期一定过期, cookie 也就被删除,所以刷

新页面,客户端向服务器端发送 cookie 时, $_COOKIE 并没有能够得到该cookie变量的值!
*/
?>

会话id默认储放在客户端Cookie中!
<?php
session_start();
print_r($_COOKIE);
?>
cookie的设置有两种方法

header('set-cookie:user=zhaofei299');
setcookie('user', 'zhaofei299');

会话变量不能被GET数据或POST数据重载!

使用session变量传递数组,对象时无需序列化!
使用session变量传递对象时,在调用session_start()之前,必须包含该对类对象的定义,反序列化

(serialize)也是如此!


删除单个会话变量可以使用unset($_SESSION['***']) 直接删除!

删除所有的会话变量不可以用unset($_SESSION),因为这样会将所有的会话信息删除,包含存储在COOKIE

中的PHPSESSID,也就是破坏了两个页面之间的会话联系,应该使用$_SESSION = array();

消除会话id,使页面之间失去联系!
session_destroy();


程序清单1.1
<?php
session_start();
header('content-type:text/html;charset=utf-8');
$_SESSION['a'] = 'a';
$_SESSION['b'] = 'b';

unset($_SESSION);        //测试后,再注释下看看
$_SESSION['user'] = 'zhaofei299';
echo 'SESSION_ID: '.session_id().'<br />';
echo '<a href="3.php" target="_blank">测试下</a>';
?>


<?php
session_start();

echo $_SESSION['user'];
echo session_id();         //会话变量改变了
?>

会话id(session_id)的两种方式传递:
1.cookie
2.url

因为默认session是基于cookie的,而cookie又是跟随http协议发送的,所以与cookie一样,在

session_start()之前不能有任何输出!

现在主要说一说第二种,通过 url 传递会话id
php中已经定义SID这个常量来得到 会话的id


sesssin_id 的使用!
<?php
session_start();
echo defined('SID')?'true':'false'; // true
echo SID; //什么也没有?
?>
为什么SID的值会是null 呢?是它哪里有问题了?
原因是因为 session 默认是基于 cookie 的,而 SID 只有 session_id 通过 url
传递数据时才会被赋值!
在浏览器中将 cookie 禁用,你就会发现 SID 有了输出,而不是 null!


删除session

要三步实现.
<?php
session_destroy();                         // 第一步: 删除服务器端session文件,这使用
setcookie(session_name(),'',time()-3600); // 第二步: 删除实际的session:
$_SESSION = array();                       // 第三步: 删除$_SESSION全局变量数组
?>

大家都知道session变量是保存在服务器端的,也就是说session的变量会保存在服务器中一个目录中,我

们可以在php.ini中的session.save_path 那里可以找到session文件中保存的地址.

默认的session的生存期是浏览的关闭就结束,但要知道会话过期结束后,当打开页面session_start()会

判断会话id 是否存在,如果不存在就创建一个,否则将该会话id 的变量载入页面!因为过期session_id会

被创建一个新的,但它保存在服务器端的session文件并没有被删除(关闭浏览器,打开session文件保存

地看看),所以要用session_destory()函数清除会话id,并同时清除相应的会话文件,这样的话才能做到最

彻底的清除!


session_id 使用 url 传递session 变量数据时,因为session_start()开启会话时会判断会话id 是否存

在,如果不存在就创建一个,否则将该会话id 的变量载入页面!
而现在是使用url 来传递session_id,然而每一次 刷新/进入页面 都会生成一个会话id,所以页面之间就

不能得到在另一页面设置过的session_id 的变量,那么使用 session也就没什么意义了!

解决方法:在session_start()之前,手动设置页面的session_id,这样页面的就可以得到前一页中所设置的

session变量的,也就实现了会话的传递,如下代码可以说明!


//已禁用 cookie

1.php
<?php
session_start();
$_SESSION['user'] = 'zhaofei299';
echo '<a href="2.php?'.SID.'">下一页</a>';
?>

1.php的第4行代码也可以写成:echo '<a href="2.php">下一页</a>';

可以设置php.ini 中的 session.use_trans_sid 为1,这样当使用 url 传递会话 id 时,
浏览器会自动将 session_id 追加到 url 的后面!
就好像 在浏览器中 输入: www.baidu.com 一样,浏览器会自动将其更换成 http://www.baidu.com/

2.php
<?php
session_id($_GET['PHPSESSID']);   // 手动设置session_id,这种就可以使用前一个页面的

session_id 的变量了,也就实现了会话!
session_start();
print_r($_SESSION);
?>

常用session函数:

bool   session_start(void); 初始化session
bool   session_destroy(void): 删除服务器端session关联文件。
string session_id() 当前session的id
string session_name() 当前存取的session名称,也就是客户端保存session ID的cookie名称.默认

PHPSESSID。
array session_get_cookie_params() 与这个session相关联的session的细节.
string session_cache_limiter() 控制使用session的页面的客户端缓存
ini    session_cache_expire() 控制客户端缓存时间
bool   session_destroy()     删除服务器端保存session信息的文件
void   session_set_cookie_params ( int lifetime [, string path [, string domain [, bool

secure [, bool httponly]]]] )设置与这个session相关联的session的细节
bool session_set_save_handler ( callback open, callback close, callback read, callback

write, callback destroy, callback gc )定义处理session的函数,(不是使用默认的方式)
bool session_regenerate_id([bool delete_old_session]) 分配新的session id    
好像三星的SyncMaster 215TW不错,还自带音响。。。
分页: 283/338 第一页 上页 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 下页 最后页 [ 显示模式: 摘要 | 列表 ]