PHP能打开远程或本地主机上的Socket端口。本文是一个使用Socket的小例子:连
接到一个Usenet新闻组服务器,同服务器对话,从新闻组中下载一些文章。
在php中打开一个socket
使用fsockopen()打开一个socket.这个函数在php3和php4种都可以使用。函数声明
是这样的:
int fsockopen (string hostname, int port [, int errno [, string errstr [, double timeout]]])
这个函数将打开一个连接到主机hostname的port端口的TCP连接。hostname可以是一
个有效的域名,或者是一个ip地址。对于udp连接,你必须指定协议:udp://hostname.
对于unix域,主机名使用到socket的路径,这种情况下,端口port必须置为0。可选
的timeout参数用来设定等待打开一个socket的时间,单位为秒。
关于fsockopen()的更多信息,请参考:h
ttp://www.php.net/manual/function.fsockopen.php
网络新闻传输协议
访问新闻组服务器需要通过称为NNTP(网络新闻传输协议)的协议来进行。这个协议
在rfc977中有详细的细节,可以在http://www.w3.org/Protocols/rfc977/rfc977.html
得到。这个文档分别描述了怎样连接到NNTP服务器,怎样同服务器对话,以及完成这
些任务的不同命令。
连接
连接到一个NNTP服务器需要知道它的主机名(或者是ip地址)和它侦听的端口。为了
避免一个连接企图失败导致程序挂起,你应该使用timeout参数。
<?php
$cfgServer = "your.news.host";
$cfgPort = 119;
$cfgTimeOut = 10;
//open a socket
if(!$cfgTimeOut)
// without timeout
$usenet_handle = fsockopen($cfgServer, $cfgPort);
else
// with timeout
$usenet_handle = fsockopen($cfgServer, $cfgPort, &$errno, &$errstr, $cfgTimeOut);
if(!$usenet_handle) {
echo "Connection failed.";
exit();
}
else {
echo "Connected.";
$tmp = fgets($usenet_handle, 1024);
}
?>
与服务器对话
现在我们已经连接到了服务器,可以通过前面打开的socket同服务器对话了。比如
说我们要从某个新闻组得到最近的10篇文章。RFC977指出,第一步要用GROUP命令选择
正确的新闻组:
GROUP ggg
PHP中 上运行 root 用户才可以运行的外部程序
在PHP中运行只有root用户才可以运行的外部程序,一直是个老问题,用常规的办法很难实现。这是因为一般情况下,PHP是作为APACHE的一个模块的,也就是说,PHP是APACHE的一部分,而APACHE除了suEXEC机制外,是不能以不同的用户ID来执行命令的,但suEXEC机制只能CGI有效。
网上曾经有一篇文章,说用调用"su - -c COMMAND"可以实现,但经过多次试验,发现不行,因为su命令必须在STDIN上输入root的密码。
怎么办?用常规的方法难以奏效,只能再想其它的方法了。成功的关键在于能有一个可以切换用户ID但又可以在命令上输入密码(或不用输入密码)的工具。有这样的工具吗?有,它就是super。
下面就具体说说如何来做?
要注意的是,安装和配置super,都要以root身份来进行。
第一步,切换到root下
第二步,安装super
先到ftp://ftp.mdtsoft.com/pub/super下载super-3.14.0-1.i386.rpm。这是一个RPM文件,其它包括了两个工具:setuid和super,以及它们的文档和man手册。用下面的命令将它安装到系统中:
% rpm -Uvh super-3.14.0-1.i386.rpm
你还可以用这个命令来查看这个RPM中的文件:
% rpm -qpl super-3.14.0-1.i386.rpm
从结果可以看到,两个工具都将被安装到/bin目录下。
第三步,配置super
super的配置文件是/etc/super.tab。这是一个文本文件,格式也比较复杂。不过,我们这里只要很简单的加上几行就可以了。至于详细的说明,可以通过man super.tab来查看。
假设运行Apache的用户是nobody,我们欲通过super来增加系统用户(调用useradd命令),那么我们只要在super.tab文件中加入以下这行:
auser /sbin/useradd nobody,hunte
第一段是super能够识别的命令的别名;第二段是该别名所对应的系统命令的全路径;第三段是可以运行该命令的用户列表,用逗号分隔。这里除了nobody外,还一个叫hunte的普通用户,是用于下面的测试。当然,你应该用你系统中有的任意一个普通用户。
至此,super的配置就算好了。
第四步,测试
以第三步中指定的非nobody用户登录,运行:
% /bin/super auser testuser
如果前面的配置没什么错误的话,用户testuser应该是成功地创建了。可以用:
% cat /etc/passwd | grep testuser
命令来验证一下。
第五步,在PHP中调用该命令
下面是PHP代码:
if ($username)
介绍smarty模板
PHP代码:--------------------------------------------------------------------------------
以下的介绍是基于2.5版的,也不知有BUG没,OS是win2000,php应该
4.1以后的就可以。,兄弟只是开发时使用过几次,没太深的研究,
介绍的在手册上都能找到,如果有错误之处难免多包涵吧
smarty模板据说是php.net推荐使用的,据说功能比较强,据说速度
也不慢,据说用的人越来越多<img src="images/smilies/biggrin.gif" border="0" alt="">
官方网站smarty.php.net上面有论坛,有下载,有手册。有你想要的一切,切入正题:
(-)安装:
下载的包解压后有三个下级目录:模板文件目录是<libs> 其下有四个类文件一个目录.首先介绍最重要的:Smarty.class.php它应该是整个smarty模板的核心类,平时应用时也是跟它打交道,在你的应用程序目录下建立以下目录结构:
/app_1/smarty/libs
/app_1/smarty/templates_c
/app_1/smarty/templates
/app_1/smarty/configs
<libs>对应压缩包下的libs目录下面放smarty需要的类文件
<templates>存放模板文件,程序用到的模板文件都放这里
<configs>存放模属性文件,以后详细说
<templates_c>存放"编译"后的模板文件,以后详细说,些目录需要设为777
<cache>存放缓存的模板文件
以上文件名为smarty默认的文件名,用户可以指定不同的文件名,如:guest_template_dir,admin_template_dir 等.如果不指定将使用以上文件名
(二)使用:
设计模板:
1模板变量:{$变量名},如 {$color},{$type}
test_color.tpl
<font color={$color}>{$name}</font>
test_url.tpl
<a href="{$url}" target="{$target}">{$title}</a>
2也可以使用模板数组
test_array.tpl
{people.name}<br>
{people.sex}<br>
{people.money}<br>
3模板使用区块列表
如:
user1 user1_sex user1_money
user2 user2_sex user2_money
user3 user3_sex user3_money
section.tpl
可以用表格格式化:
<TABLE>
{section name=user loop=$userList}
<TR>
<TD>{$userList[user].name}</TD>
<TD>{$userList[user].sex}</TD>
为加速 PHP 程序而努力
动态网站的内容加速显示十分重要,本文通过对 PHP 几个函数的深入讨论,提出了 PHP 网页压缩和缓冲的解决方案
一、介绍几个控制 PHP 输出的函数
PHP4 采用了缓冲机制,在你决定发送以前,所有内容只是存在于缓冲中,而不是直接发送给浏览器,虽然你可以用 header 和 setcookie 函数来实现,但是这两个函数相比于功能强大的输出函数来说只是一点“雕虫小技”。让我们来看看这些函数的真本事:
void ob_start(void);
本函数告诉 PHP 处理器把所有输出重定向到内部缓冲,调用这个函数后,就不会有输出到浏览器。
string ob_get_contents(void);
本函数把输出缓冲返回到一个字符串,你可以用来把堆积起来的输出一起发送到浏览器。当然要先关掉缓冲。
int ob_get_length(void);
本函数返回输出缓冲的长度。
void ob_end_clean(void);
本函数清除并关闭缓冲。在输出到浏览器之前你需要使用这个函数。
void ob_implicit_flush ([int flag])
本函数用来控制隐式缓冲泻出,缺省为 off,如果打开时,对每个 print/echo 或者输出命令的结果都发送到浏览器。
二、采用输出控制来压缩 PHP 的输出
在开始之前,要保证你的 PHP4 编译时支持 Zlib。
首先,初始化输出缓冲:
ob_start();
ob_implicit_flush(0);
然后产生所有的输出内容。
print("本例为压缩输出!");
页面生成以后,采用:
$contents = ob_get_contents();
ob_end_clean();
还要检查浏览器是否支持压缩数据,我们采用在变量 $HTTP_ACCEPT_ENCODING 中检查 "gzip, deflate"的办法:
if(ereg(gzip, deflate,$HTTP_ACCEPT_ENCODING)) {
// 产生 gzip 后的内容
} else {
echo $contents;
}
下面我们分析怎样产生 gzip 输出:
// 告诉浏览器下面接收的是 gzip 数据。
header("Content-Encoding: gzip");
// 显示 gzip 文件的文件头
// 只要一次就够了
echo "x1fx8bx08x00x00x00x00x00";
// 计算长度和 CRC 校验码
$Size = strlen($contents);
$Crc = crc32($contents);
// 压缩数据
$contents = gzcompress($contents, 9);
// 不能直接在这里输出内容,因为还没有写入 CRC 呢!
$contents = substr($contents, 0, strlen($contents) - 4);
如何将gbk编码转成utf8格式
apache 字符集 GB 2312
mysql 字符集 GBK
现要从 mysql 中提出信息(GBK) 写入到 XML 中
XML中的编码格式是 UTF-8
那么,如何将GBK编码成 UTF8 ??
详细介绍:
前一阵子见到了qiushuiwuhen君的关于gbk,unicode,big5的转换的文章
但是多少有一些不太大的问题
于是我设计了一个负责字符转换的类,修正了其中的一些不足,增加了部分功能,以后我会不断扩充该类,来支持更多的字符集
增加了如下几点:
unicode->gbk 符号部分的转换
欧元符(
新作模板处理类,有兴趣的可以试试
pfcTemplate 主要特点
1. 高效率
因为程序中分析变量、区块时没有采用正规表达式去做,而采用PHP内置字符串
处理函数来做,所以效率可能会稍高于同类产品
2. 易用性
使用此类只需简单的 创建类实例 -> 添加文件 -> 设置变量/区块 -> [如果有区块则解析]
-> 解析文件 就可以完成. 采用常用的命名方式, 提供通俗易懂的API接口方法.
3. 多级区块处理
通过程序的多级区块处理功能可以实现很多复杂的效果, 可以进行无限层次的套嵌(机器性能允许)
4. 可处理多种来源的模板
模板不一定要做成文件, 可以是来自数据库或其它来源.
$str = read_template_string();
$tpl->set_string(handle1, $str);
5. 变量可定制性
模板中的标识符是可以自行调整的.
如: 将简单变量的标识符定制为 "{/var
用PHP制作zip压缩程序
刚在网上找的一个类。点击下载类文件(zip压缩文件,2.25K)
$z = new PHPZip(); //新建立一个zip的类
方法一:
$z -> Zip("", "out1.zip"); //添加当前目录和子目录下的所有档案
方法二:
$files=array(1.txt,gb.txt);
$files[]=5.txt;
$z -> Zip($files, "out2.zip"); //添加文件列表
方法三:
$z -> Zip("/usr/local/sext/", "out3.zip"); //添加指定目录
对盗链说再见...
第一页内随机的产生一个数(0-15)-》dechex()保存在session内
然后将URL使用此标记进行运算,随便你运算了,不过要能逆过来才行~
第二页则检测是否有此标记,有则进行逆运算,然后将变量取出
优点:(必须访问站点URL才有效~)
缺点:(保存到本地的页面链接全部失效,盗链失效)
---------------------------------------------
<?php
ob_start();
session_start();
if(isset($_SESSION[key]))else{ //无钥匙
$key=dechex(rand(0,15)); //产生钥匙
//如果您本页已经是最后一页,而不允许盗链的链接的话
//echo "您的链接并非来自本站!请访问站点后访问此页...";
//exit();
}
?>
HTML内容..............(这里包含很多链接的...)
<?php
$htmlcontent=ob_get_contents(); //获取所有HTML内容
............................... //替换所有连接参数href=url?被替换的数据(一组正则)
ob_end_flush(); //输出HTML内容(href=已经加密后的数据)
?>
多php服务器实现多session并发运行
首先介绍一下session的概念:
所谓session是微软首先提出的,在asp中最先集成。由于session的采用,大大方便了web开发员的工作。一时间asp风靡全球。现在php4也加入session的支持,再度显示出open source 的强大力量。和Cookie类似,设计Session的目的也是为了在一个访问期间在不同的页面间传输数据以解决http协议无状态的问题,但Session更加简单、更加安全。Session 中文没有一个统一的译法,我习惯上译为会话。关于session的意义大家都应该清楚: 其实是在浏览某个网站时,在浏览器没有关闭的情形之下,一个web应用的开始和结束。一个session可以包括数次http的请求和应答,比如我们用freemail.263.net,从login到logout或者超时就作为一个session 的生存期。每一个被创建的Session都有一个唯一的标识串,叫session ID , 这个串被发送到客户端,同时在服务器端也生成了同样唯一的标识串入口,这个标识串或者放在文本文件中,或者放在一个数据库中。然后程序可以在这个sessionID下注册一些Session 变量。这些变量如同一般的变量一样可以保存文本或数值信息,可以通过Session被读出或写入。
session 的唯一标识一般是在系统内部唯一的session ID,一般是一个挺长的字符串。
问题的提出:
解了session概念后,我在为我单位编写一个进销存系统中发现需要让多个用户可以同时进入一个php应用程序。原来设计的静态的唯一的session ID导致数据混乱。这样,动态生成一个唯一的session ID成为当务之急。
解决办法很简单:我用了php文件名+时间戳为唯一的session ID,这样在我的程序中的每个session就各就各位,不再混乱了。
下面把我的源代码公布,方便也有同样的问题的朋友多一个解决方法。
//Start a PHP session to preserve variables.
if ( empty($mysessionname) ) {
$micro = microtime();
$micro = str_replace(" ","",$micro); // strip out the blanks
$micro = str_replace(".","",$micro); // strip out the periods
$mysessionname = "po_maint" . $micro;
}
session_name($mysessionname);
session_start();
程序注释:
我用mysessionname为页面间唯一的sessionname传递变量,如果你也用到这个名字必须把上述程序做个小小的改动。Mysessionname不能为session的内部变量名,因为他在session开始之前就已经存在了。Mysessionname也不能用cookie方式存放,因为多个session肯定会覆盖掉原先的cookie文件。你可以用隐含表单的域来保存它。这样就不会有问题。欢迎来信讨论。让我们一起做得更好。
phplib里带的模板功能的确非常好用,但有个致命的小错误需要更正
phplib里带的template.inc包含了一个模板类,用它可以实现程序代码和
界面的分离,给程序设计和界面设计带来了极大的方便,而且它的实现比快速
模板要好。但有一个致命的小错误导致set_block()函数不能正常使用,而这个
函数是非常重要的,它在处理重复块时显得非常的好用。
下面通过一个最简单的例子来讲解用法及解决方法:
模板文件:page1.ihtml(名字你可以随便取,后缀ihtml是一种习惯用法)
<HTML>
<HEAD>
<TITLE> {TITLE} </TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF">
<!-- BEGIN TBK -->
ID: {ID}<BR>
NAME: {NAME}<BR>
<HR>
<!-- END TBK -->
</BODY>
</HTML>
处理文件:test.php
<?php
include("./template.inc");
# 创建模板变量$t
$t = new Template(".", "keep");
# 定义页面变量的引用,这样你就可以用page1来引用页面了
$t->set_file("page1","page1.ihtml");
# 提取名称为TBK的块,让它指向tbks的引用
$t->set_block("page1", "TBK", "tbks");
# 替换标题TITLE变量
$t->set_var("TITLE","my test of template");
# 定义ID和NAME,然后把TBK附加到tbks
for ($i=1; $i<=3; $i++) {
$n = $i;
$nn = $i*10;
$t->set_var(array("ID" => $n, "NAME" => $nn));
$t->parse("tbks", "TBK", true);
}
# 最后输出页面
$t->pparse("out", "page1");
PHP:MVC迷思
近来设计模式风行,MVC随处可见,PHP领域也不例外,很多论坛都开始讨论在PHP中使用MVC。然而,M、V、C在PHP中到底该如何实现?MVC真的适合PHP么?这里Easy给出一些自己的思考。
MVC的原型
MVC本来是存在于Desktop程序中的,M是指数据模型,V是指用户界面,C则是控制器。使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式。比如一批统计数据你可以分别用柱状图、饼图来表示。C存在的目的则是确保M和V的同步,一旦M改变,V应该同步更新。
JAVA中的MVC
JAVA把MVC引入了Web领域,并在此基础上架构出了一套称为Model2的体系。由于Web的特殊性,JAVA中的MVC和Desktop中的MVC并不完全一致。主要原因是Web中的V不是持续的,用户每访问一次,V就要重新生成一次,所以V始终是和M一致的,不需要C来控制同步。那么JAVA中的C在干什么?JAVA中的C通常用于流程的转向,其实用的是Dispatch模式,不再是Desktop中的C了。
PHP中的MVC
要在PHP中原封不动的COPY JAVA的MVC是不可能的。问题主要表现在M上,在JAVA中,M是独立于业务逻辑和表现逻辑的数据模型,在服务器端跨页面存在,JAVA Bean扮演的就是这个脚色。而PHP进程并不长时间驻留于内存,只在PHP页面开始执行时创建,在页面解释执行结束时就已经结束。在这样的情况下,我们根本无法直接实现M。所以所有声称实现了MVC模式的PHP程式都只能通过模拟手段来实现M。实现的方式一般是在当前页面结束前把数据存入数据库或者cookie/session,在下一个页面中再透过数据库或者cookie/session重建M。这样的方式和JAVA中的Bean比起来可以说是开销巨大,本来往内存中写数据的简单操作现在要从服务器端传到客户端或者数据库,然后再传回来。与其用这么大的开销来维护一个数据模型再在最后把这个模型塞回数据库,还不如直接根据需要更新数据库里边的数据。
第二节--PHP5 的对象模型 -- Classes and Objects in PHP5 [2]
第二节--PHP5 的对象模型
PHP5有一个单重继承的,限制访问的,可以重载的对象模型. 本章稍后会详细讨论的”继承”,包含类间的父-子关系. 另外,PHP支持对属性和方法的限制性访问. 你可以声明成员为private,不允许外部类访问. 最后,PHP允许一个子类从它的父类中重载成员.
//haohappy注:PHP4中没有private,只有public.private对于更好地实现封装很有好处.
PHP5的对象模型把对象看成与任何其它数据类型不同,通过引用来传递. PHP不要求你通过引用(reference)显性传递和返回对象. 在本章的最后将会详细阐述基于句柄的对象模型. 它是PHP5中最重要的新特性.
有了更直接的对象模型,基于句柄的体系有附加的优势: 效率提高, 占用内存少,并且具有更大的灵活性.
在PHP的前几个版本中,脚本默认复制对象.现在PHP5只移动句柄,需要更少的时间. 脚本执行效率的提升是由于避免了不必要的复制. 在对象体系带来复杂性的同时,也带来了执行效率上的收益. 同时,减少复制意味着占用更少的内存,可以留出更多内存给其它操作,这也使效率提高.
//haohappy注:基于句柄,就是说两个对象可以指向同一块内存,既减少了复制动作,又减少对内存的占用.
Zand引擎2具有更大的灵活性. 一个令人高兴的发展是允许析构--在对象销毁之前执行一个类方法. 这对于利用内存也很有好处,让PHP清楚地知道什么时候没有对象的引用,把空出的内存分配到其它用途.