|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
开发相册系统过程中就有过这样的问题,因为没有交流好,出现重复工作问题,因为文档没有详细的说明而经常临时问对方。 有无举措在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 ($r socket_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遍,我说的这个读是自己看。 |
|