其实学习,最好的方法就是自己整理资料,分享给别人,通过整理能有更清晰的思路,不至于混成一锅粥,此外,能给别人讲清楚,说明你自己已经掌握了要点。
首先,对socket有个简单的认识,socket网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。
推荐一篇博客来熟悉socket的原理机制:
http://blog.csdn.net/hguisu/article/details/7445768/
总结:
Socket,从服务端的的角度来讲,最基本的就是三步走:
创建->绑定->监听 。
从整个socket通信角度来讲,就是:
服务端监听->客户端连接并发送数据->服务端接收数据 (以及后续处理)。
以上基础掌握之后,我们再来学习一下如何进行socket多进程处理请求。这个是为了解决:
当一个连接长时间占用当前进程时,后面来的请求就必须要等待,这会导致处理请求的速度很低,那么解决的方案就是,使用多个进程,当每发来一个请求时,就开启一个进程进行处理,为了区别单进程和多进程的区别,我们还是看一下代码是如何写的:
首先是单进程服务端代码:
<?php
$socket = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
socket_bind($socket,'127.0.0.1',9090) or die('error');
socket_listen($socket,5);
while(true){
$client = socket_accept($socket); // 有人打电话进来
$buf = socket_read($client,1024); // 一次读取1024的长度
echo $buf;
if(preg_match('/sleep/i',$buf)){
sleep(10);
$html = 'HTTP/1.1 200 OK'.PHP_EOL
.'Content-Type: text/html;charset=utf-8'.PHP_EOL.PHP_EOL;
socket_write($client,$html);
socket_write($client,'this is server,休克了10秒,模拟很繁忙的样子');
}else{
socket_write($client,'this is server');
}
socket_close($client);
}
socket_close($socket);
多进程的代码:
<?php
$socket = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
socket_bind($socket,'127.0.0.1',9090) or die('error');
socket_listen($socket,5);
while(true){
$client = socket_accept($socket);
//创建紫金城
$pid = pcntl_fork();
//父进程和子进程都会执行下面代码
if ($pid == -1) {
//错误处理:创建子进程失败时返回-1.
die('could not fork');
} else if ($pid) {
//父进程会得到子进程号,所以这里是父进程执行的逻辑
//pcntl_wait($status); //等待子进程中断,防止子进程成为僵尸进程。
socket_close($client);
} else {
//子进程得到的$pid为0, 所以这里是子进程执行的逻辑。
$buf = socket_read($client,1024);
echo $buf;
if(preg_match('/sleep/i',$buf)){
sleep(10);
$html = 'HTTP/1.1 200 OK'.PHP_EOL
.'Content-Type: text/html;charset=utf-8'.PHP_EOL.PHP_EOL;
socket_write($client,$html);
socket_write($client,'this is server,休克了10秒,模拟很繁忙的样子');
}else{
socket_write($client,'this is server');
}
socket_close($client);
}
}
socket_close($socket);
这里重点是掌握
pcntl_fork()这个函数的使用,如果没有安装这个拓展的需要安装一下;
<?php
$pid = pcntl_fork();
//父进程和子进程都会执行下面代码
if ($pid == -1) {
//错误处理:创建子进程失败时返回-1.
die('could not fork');
} else if ($pid) {
//父进程会得到子进程号,所以这里是父进程执行的逻辑
pcntl_wait($status); //等待子进程中断,防止子进程成为僵尸进程。
} else {
//子进程得到的$pid为0, 所以这里是子进程执行的逻辑。
}
?>
这是php.net 手册里给的案例,看不懂的可以去查一下手册;
但是很明显,采用这样的多进程处理方式,当请求成千上万时,开销很大,所以显然不是高效的,如何优化呢,此处推荐一篇博客:
http://blog.csdn.net/hguisu/article/details/7448528