若相依 发表于 2015-2-3 23:30:05

PHP教程之奇妙处理PHP没法完成多线程的成绩

开发相册系统过程中就有过这样的问题,因为没有交流好,出现重复工作问题,因为文档没有详细的说明而经常临时问对方。    有无举措在PHP中完成多线程呢?假定你正在写一个基于多台办事器的PHP使用,幻想的情形时同时向多台办事器发送恳求,而不是一台接一台。可以完成吗?当有人想要完成并发功效时,他们凡是会想到用fork或spawn threads,然而当他们发明PHP不撑持多线程的时分,也许会转换思绪去用一些不敷好的言语,好比Perl。
   
其实的是大多半情形下,你大可不用利用fork或线程,而且你会失掉比用fork或thread更好的功能。假定你要创立一个办事来反省正在运转的n台办事器,以肯定他们还在正常运转。你能够会写上面如许的代码:

[*] $hosts = array("host1.sample.com", "host2.sample.com", "host3.sample.com");
[*] $timeout = 15;   
[*] $status = array();   
[*] foreach ($hosts as $host) {   
[*]         $errno = 0;   
[*]         $errstr = "";   
[*]         $s = fsockopen($host, 80, $errno, $errstr, $timeout);   
[*]         if ($s) {   
[*]            $status[$host] = "Connectedn";   
[*]            fwrite($s, "HEAD / HTTP/1.0rnHost: $hostrnrn");   
[*]             do {      
[*]               $data = fread($s, 8192);      
[*]               if (strlen($data) == 0) {      
[*]               break;      
[*]               }      
[*]            $status[$host] .= $data;   
[*]          }   
[*]          while (true);   
[*]             fclose($s);   
[*]         }   
[*]          else {   
[*]               $status[$host] = "Connection failed: $errno $errstrn";   
[*]          }   
[*] }   
[*] print_r($status);   
[*] ?>
它运转的很好,然而在fsockopen()剖析完hostname而且创立一个胜利的毗连(或延时$timeout秒)之前,扩大这段代码来办理大批办事器将消耗很长工夫。
因而咱们必需保持这段代码;咱们可以创立异步毗连-不需求守候fsockopen前往毗连形态。PHP依然需求解析hostname(所以直接利用ip加倍明智),不外将在翻开一个毗连以后立即前往,继而咱们就能够毗连下一台办事器。
有两种办法可以完成;PHP5中可使用新增的stream_socket_client()函数直代替换失落fsocketopen()。PHP5之前的版本,你需求本人下手,用sockets扩大处理成绩。上面是PHP5中的处理办法:

[*] $hosts = array("host1.sample.com", "host2.sample.com", "host3.sample.com");
[*] $timeout = 15;   
[*] $status = array();   
[*] $sockets = array();   
[*] /* Initiate connections to all the hosts simultaneously */   
[*] foreach ($hosts as $id => $host) {   
[*]         $s = stream_socket_client("$host:80", $errno, $errstr, $timeout,   
[*]            STREAM_CLIENT_ASYNC_CONNECTSTREAM_CLIENT_CONNECT);   
[*]         if ($s) {   
[*]             $sockets[$id] = $s;   
[*]             $status[$id] = "in progress";   
[*]         }   
[*]         else {$status[$id] = "failed, $errno $errstr";   
[*]         }   
[*] }   
[*] /* Now, wait for the results to come back in */   
[*]   
[*] while (count($sockets)) {   
[*]       $read = $write = $sockets;   
[*] /* This is the magic function - explained below */   
[*]       $n = stream_select($read, $write, $e = null, $timeout);   
[*]       if ($n > 0) {   
[*]       /* readable sockets either have data for us, or are failed   * connection attempts */   
[*]         foreach ($read as $r) {         
[*]                  $id = array_search($r, $sockets);         
[*]                  $data = fread($r, 8192);         
[*]         if (strlen($data) == 0) {      
[*]                  if ($status[$id] == "in progress") {      
[*]                        $status[$id] = "failed to connect";      
[*]                  }      
[*]         fclose($r);      
[*]         unset($sockets[$id]);         
[*]            }   
[*]            else {      
[*]                  $status[$id] .= $data;         
[*]            }   
[*]         }   
[*] /* writeable sockets can accept an HTTP request */   
[*] foreach ($write as $w) {      
[*]          $id = array_search($w, $sockets);      
[*]          fwrite($w, "HEAD / HTTP/1.0rnHost: "      
[*]          . $hosts[$id] ."rnrn");      
[*]          $status[$id] = "waiting for response";   
[*]          }   
[*] }   
[*] else {   
[*] /* timed out waiting; assume that all hosts associated   * with $sockets are faulty */   
[*] foreach ($sockets as $id => $s) {      
[*]          $status[$id] = "timed out "   
[*]          . $status[$id];   
[*]          }   
[*] break;   
[*]   }   
[*] }   
[*] foreach ($hosts as $id => $host) {   
[*]       echo "Host: $hostn"; echo "Status: "   
[*]       . $status[$id] . "nn";   
[*] }   
[*] ?>
咱们用stream_select()守候sockets翻开的毗连事务。stream_select()挪用体系的select(2)函数来工 作:后面三个参数是你要利用的streams的数组;你可以对其读取,写入和获得异常(分离针对三个参数)。stream_select()可以经由过程设 置$timeout(秒)参数来守候事务产生-事务产生时,响应的sockets数据将写入你传入的参数。
上面是PHP4.1.0以后版本的完成,假如你已在编译PHP时包括了sockets(ext/sockets)撑持,你可使用根下面相似的代 码,只是需求将下面的streams/filesystem函数的功效用ext/sockets函数完成。次要的分歧在于咱们用上面的函数取代 stream_socket_client()来创立毗连:

[*] // This value is correct for Linux, other systems have other values
[*] define('EINPROGRESS', 115);   
[*] function non_blocking_connect($host, $port, &$errno, &$errstr, $timeout) {   
[*]         $ip = gethostbyname($host);   
[*]         $s = socket_create(AF_INET, SOCK_STREAM, 0);   
[*]         if (socket_set_nonblock($s)) {   
[*]            $r = @socket_connect($s, $ip, $port);   
[*]            if ($rsocket_last_error() == EINPROGRESS) {      
[*]                   $errno = EINPROGRESS;      
[*]                   return $s;   
[*]                }   
[*]          }   
[*]         $errno = socket_last_error($s);   
[*]         $errstr = socket_strerror($errno);   
[*]         socket_close($s);   
[*]         return false;   
[*] }   
[*] ?>
如今用socket_select()交换失落stream_select(),用socket_read()交换失落fread(),用socket_write()交换失落fwrite(),用socket_close()交换失落fclose()就能够履行剧本了! PHP5的先辈的地方在于,你可以用stream_select()处置几近一切的stream。例如你可以经由过程include STDIN用它吸收键盘输出并保留进数组,你还可以吸收经由过程proc_open()翻开的管道中的数据。
怎么样出来了吧,怎么样自己也可以写出php程序了,虽然离职业和专业的人还有很远,但是好的开始是成功的一半。这个时候改怎么做了呢。现在就是拿1本高手推荐的书,重头到尾读1遍,我说的这个读是自己看。

乐观 发表于 2015-2-3 23:48:43

首先我是坚决反对新手上来就用框架的,因为对底层的东西一点都不了解,造成知识上的真空,会对以后的发展不利。我的观点上手了解下框架就好,代码还是手写。当然啦如果是位别的编程语言的高手的话,这个就另当别论啦。

活着的死人 发表于 2015-2-9 07:35:36

再就是混迹于论坛啦,咱们的phpchina的论坛就很强大,提出的问题一般都是有达人去解答的,以前的帖子也要多看看也能学到不少前辈们的经验。别的不错的论坛例如php100,javaeye也是很不错的。

冷月葬花魂 发表于 2015-2-27 04:29:59

要进行开发,搭建环境是首先需要做的事,windows下面我习惯把环境那个安装在C盘下面,因为我配的环境经常出现诡异事件,什么事都没做环境有的时候就不能用啦。

小魔女 发表于 2015-2-27 20:39:19

使用zendstdio 写代码的的时候,把tab 的缩进设置成4个空格是很有必要的

柔情似水 发表于 2015-3-6 20:09:36

建数据库表的时候,int型要输入长度的,其实是个摆设的输入几位都没影响的,只要大于4就行,囧。

蒙在股里 发表于 2015-3-11 00:10:48

本人接触php时间不长,算是phper中的小菜鸟一只吧。由于刚开始学的时候没有名师指,碰过不少疙瘩,呗很多小问题卡过很久,白白浪费不少宝贵的时间,在次分享一些子的学习的心得。

灵魂腐蚀 发表于 2015-3-17 16:15:10

写的比较杂,因为我也是个新手,不当至于大家多多指正。

只想知道 发表于 2015-3-24 12:06:19

Ps:以上纯属原创,如有雷同,纯属巧合

变相怪杰 发表于 2015-3-25 10:29:44

在学习的过程中不能怕麻烦,不能有懒惰的思想。学习php首先应该搭建一个lamp环境或者是wamp环境。这是学习php开发的根本。虽然网络上有很多集成的环境,安装很方便,使用起来也很稳定、

仓酷云 发表于 2015-4-2 16:26:39

找到的的资料很多都是在论坛里的,需要注册,所以我一般没到一个论坛都注册一个id,所有的id都注册成一样的,这样下次再进来的时候就不用重复注册啦。当然有些论坛的某些资料是需要的付费的。

再见西城 发表于 2015-4-11 10:18:48

当然这种网站的会员费就几十块钱。

飘飘悠悠 发表于 2015-4-21 06:43:27

因为blog这样的可以让你接触更多要学的知识,可以接触用到类,模板,js ,ajax

小妖女 发表于 2015-5-1 20:09:05

php里的数组为空的时候是不能拿来遍历的;(这个有点低级啊,不过我刚被这个边界问题墨迹了好长一会)

第二个灵魂 发表于 2015-5-1 21:12:10

使用zendstdio 写代码的的时候,把tab 的缩进设置成4个空格是很有必要的

若相依 发表于 2015-5-4 14:20:01

装在C盘下面可以利用windows的ghost功能可以还原回来(顺便当做是重转啦),当然啦我的编译目录要放在别的盘下,不然自己的劳动成果就悲剧啦。

莫相离 发表于 2015-5-11 22:38:34

找到的的资料很多都是在论坛里的,需要注册,所以我一般没到一个论坛都注册一个id,所有的id都注册成一样的,这样下次再进来的时候就不用重复注册啦。当然有些论坛的某些资料是需要的付费的。

深爱那片海 发表于 2015-6-15 03:16:54

遇到出错的时候,我经常把错误信息直接复制到 google的搜索栏,一般情况都是能搜到结果的,不过有时候会搜出来一大片英文的出来,这时候就得过滤一下,吧中文的弄出来,挨着式方法。

山那边是海 发表于 2015-6-19 16:36:48

真正的方向了,如果将来要去开发团队,你一定要学好smarty ,phplib这样的模板引擎,

透明 发表于 2015-6-27 21:12:39

本人接触php时间不长,算是phper中的小菜鸟一只吧。由于刚开始学的时候没有名师指,碰过不少疙瘩,呗很多小问题卡过很久,白白浪费不少宝贵的时间,在次分享一些子的学习的心得。
页: [1] 2
查看完整版本: PHP教程之奇妙处理PHP没法完成多线程的成绩