单进程
要学习socket多进程,先来看看什么是单进程。
服务端server.php代码如下:
<?php
$socket = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
socket_bind($socket,'10.211.55.13',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);
代码解释,上面代码中我们做了一个判断,如果请求的地址中有sleep
关键字,就『休克』10秒,来模拟单进程处理繁忙的状态。
我们可以想象:当我们直接在浏览器中请求http://10.211.55.13:9090/
,会马上给我们返回this is server
内容,而当我们请求http://10.211.55.13:9090/?sleep
,浏览器则会等待10秒,才返回this is server,休克了10秒,模拟很繁忙的样子
。
从上面动图可以看出:一个请求”卡住了”,另外一个请求也进入”等等状态”,这就是单进程的缺陷。
我们通过Linux命令查看也只有一个进程在执行server.php
ps -ef |grep server.php
或者根据占用的9090端口查看进程:
netstat -anp | grep 9090
多进程
php的socket多进程,是需要安装一个名为pcntl
扩展的,安装方法请自行百度。
执行:
php -m #查看安装的php扩展
关于php多进程的资料:
http://php.net/manual/zh/book.pcntl.php
http://php.net/manual/zh/function.pcntl-fork.php
下面是我们改造后的服务端server.php的代码:
<?php
$socket = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
socket_bind($socket,'10.211.55.13',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);
从上面动图可以看出:浏览器多个请求,并没有发生”卡住了”的现象。
使用命令查看进程数,果然不是只有一个了。