当我们需要在不同服务器或者不同的语言之间做数据交换,我们有一种方法是用Socket做数据代理。Socket是源于UNIX的套接字,基于TCP/IP协议,是从UNIX早期的命令集中演化而来的,基础的模式是“连接-读写-关闭”。Socket可以应用于B/S和C/S两种不同的网络软件架构上,现在已经被广泛的引用。
php的Socket模块虽然相对比较简陋,一些复杂的应用会出现一些莫名奇妙的问题,但是单单作为基础的数据代理来讲还是经受了人们的检验。
一、Socket传输的是什么
Socket传输的是字节流,没有定义边界。只是通过调节缓冲区的大小来完成流的截断,当然设置缓冲区的大小都是必须的,否则Socket也许会一直工作下去。Socket传输的数据很容易被截取并且会直接展示出来,所以你通常需要对你的数据进行加密,比如AES,就是很好的加密算法,不要用MD5这样的散列表,否则你会死得很惨。
PHP似乎想要get字节流加上边界,在它的socket_write这个函数中声明的三个参数,它的文档里面说如果你将第三个参数设置为PHP_NORMAL_READ,那么将会读取到/r或者/n,可惜,当我这样做的时候,程序溢出了。原因至今不明。
二、用php做一个SocketServer
我们先抛弃类,这篇将没有一个类定义出现。
前面我们已经说了Socket的工作模式是“连接-读写-关闭”。作为服务器,我们要做的事情是建立一个socket,绑定一个端口,然后监视每一个连接,读取他们传来的消息,并给予他们反馈,然后将这个连接毙掉。现在我们开始
< ?php
//===================
//SockServ.php
//===================
define(’SOCKIP’, ‘localhost’);
define(’SOCKPORT’, ‘12345′);
/**
* Set up our socket
*/
$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); //创建一个socket
printf("Socket created.\r\n");
socket_bind($sock, SOCKIP, SOCKPORT); //绑定一个端口
socket_listen($sock); //开始监视了
printf("Socket has set up.\r\n\r\n");
while(true) {
$conn = socket_accept($sock); //抓到一个,允许它的连接
if ($conn) {
printf("==========================================\r\n");
printf("Socket connected.\r\n");
while($data = socket_read($conn, 1024)) {
//千万不能加上PHP_NORMAL_READ啊
$buffer = $data;
printf("Data Received.\r\n");
print_r("Buffer: ".$buffer."\r\n");
socket_write($conn, "OK"); //告诉客户端,OK,我收到了
printf("Successed!\r\n");
}
socket_close($conn); //工作完成,你可以去了
printf("Closed the socket\r\n");
printf("==========================================\r\n\r\n");
}
}
?>
上面这段程序,你最好别用浏览器来跑,你可能会得到一个超时,你应该在命令行里面跑。在服务器上,让它跑在后台,然后就让它呆在那里吧,没事的。
三、还有客户端呢
我们当然还需要一个客户端,不然你执行上面程序时会一直停在“Socket has set up.”。客户端的任务就是在浏览器里打开一张页面程序,向服务器端发送那么一个字符串,然后接受服务器返回的“OK”。我们开始吧
< ?php
//===================
//SockClient.php
//===================
define(’SOCKIP’, ‘localhost’);
define(’SOCKPORT’, ‘12345′);
$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); //创建一个socket
$connStat [...]
Full story »
PHP5带给我们的面向对象的变化是伟大的是空前的是胜利的,就像所有的两会一样。尤其是它提供给我们的那些魔术函数,更是像桂林山水一样令人流连忘返。
1. __construct() 构造函数
这是PHP默认的构造函数,它并不能主动被程序调用只能是在对象创建的时候被自动调用。同时为了向下兼容,PHP5也支持与类同名的构造函数,值得一提的是当两种构造函数同时存在的时候,__construct()将不会被调用。
2. __destruct() 析构函数
3. __get($key)
当读取一个不存在的属性时调用。
< ?php
class Obj {
public function __get($key) {
echo $key.’ is not exsit’;
}
}
$obj = new Obj();
echo $obj->varnotexist;
?>
上面的这段程序将会输出:varnotexist is not exist。
4. __set($key, value)
与__get($key)类似,而它是在修改一个不存在的属性时被调用。
5. __call($key, $args)
与__get($key)类似,而它是在调用一个不存在的方法时被调用。
6. __toString()
在试图打印一个对象时被调用
< ?php
class Obj {
private $a;
private $b;
public function __construct() {
$this->a = ‘a’;
$this->b = ‘b’;
}
public function __toString() {
echo $this->a.’|’.$this->b;
}
}
$obj = new Obj();
echo $obj;
?>
此时程序会打印:a|b
7. __clone()
当对象被克隆的时候被打印。
< ?php
class Obj {
public function __clone() {
echo [...]
Full story »
PHP的面向对象的特性越来越完善使得,PHP能够更好的从代码结构上进行系统的封装。当一个系统,其中有大量的逻辑存在与流程控制之中,MVC的优势就开始渐渐体现。
MVC的模式要求对系统的总体结构在逻辑上分成三部分
View(界面/视图):用户界面,网页模板
Controller(控制/流程):系统业务流程
Model(模型/逻辑):系统设计中的一些基础类和数据操作
拿一个简单的登陆流程当例子
最常见的登陆流程是这样的,我们假设我们的网站根目录下有一个叫做/user的文件夹来存放所有与用户操作相关的页面,其中有一个页面是/user/login.php。而我们的根目录上有文件/index.php作为网站的首页。当我们打开/index.php的时候进行判断,如果未登陆则跳转到/user/login.php进行登陆,如果成功则跳回/index.php,否则跳到/error.php。
流程图如下:
根据文字和流程图的描述,我们可以开始编码了。
/index.php
< ?php
//…
$userLib = new userLib();
if (!$userLib->chkLogin()) header(’location: /user/login.php’);
//…
?>
/user/login.php
< ?php
//…
if (isset($_POST[’submit’])) {
$userLib = new userLib();
$succ = $userLib->login($_POST[’name’], $_POST[’pass’]);
header(’location: ‘.($succ?’/index.php’:'/error.php’));
}
$tpl = new Template();
$tpl->show(’user_login.tpl’);
?>
/error.php
< ?php
$tpl = new Template();
$tpl->show(’error.tpl’);
?>
关于Controller
就像上面三段程序就是系统中的controller,他们并不执行什么具体的操作也不输出,只是不断调用Model中的不同方法来处理逻辑。
关于Model
Model则是另一个重要的话题,那便是在PHP中如何更好的类封装。但是在这里我们看到的在/user/login.php中被使用的userLib类和Template类都是系统中的model,他们处理具体的数据操作,并返回值来用controller使用。
从PHP5开始,我们有了接口,从PHP5.3开始,虽然还没有Release,我们有了namespace,PHP真正面向对象的时代已经到来了。这时候我们已经没有必要再去讨论我们应该把userLib写成userLib.function.php还是userLib.class.php,我们要做的只是更好的封装和理解各model之间的从属逻辑结构。更好的设计model中的各个库来保障系统的运行效率和维护效率。
关于View
View的部分往往被看作是前段设计人员的工作,但是作为PHP的程序员也必须关注这一话题。
对于view和controller来说,所有的页面都是围绕着流程来产生的。而controller有时也担负着处理页面与页面之间相互传递的工作。我们要确定页面的元素,特别是表单元素,并通过表单元素来处理用户提交的数据,其次我们还要确定PHP传递给模板的变量,然后才能交付给设计人员。
最后
我们还经常用来一些常用的文件夹名和文件名来暗示程序的阅读者,特别是新的阅读者,该文件夹或文件的作用。这也是相当重要的。
Full story »