问题:
有没有办法在php中实现多线程呢?

假设你正在写一个基于多台服务器的php应用,理想的情况时同时向多台服务器发送请求,而不是一台接一台。
可以实现吗?
回答:

当有人想要实现并发功能时,他们通常会想到用fork或者spawn threads,但是当他们发现php不支持多线程的时候,大概会转换思路去用一些不够好的语言,比如perl。

其实的是大多数情况下,你大可不必使用fork或者线程,并且你会得到比用fork或thread更好的性能。

假设你要建立一个服务来检查正在运行的n台服务器,以确定他们还在正常运转。你可能会写下面这样的代码:

<?php
$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中的解决方法:

<?php
$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_CONNECT|STREAM_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()来建立连接:

<?php
// 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()打开的管道中的数据。
如 果你想让PHP4.3.x自身拥有处理streams的功能,我已经为你准备了一个让fsockopen可以异步工作的patch。不赞成使用该补丁,该 补丁不会出现在官方发布的PHP版本中,我在补丁中附带了stream_socket_client()函数的实现,通过它,你可以让你的脚本兼容 PHP5。
附件:
documentation for stream_select()
documentation for socket_select()
patch for PHP 4.3.2 and script to emulate stream_socket_client(). (might work with later 4.3.x versions).

转载于:https://www.cnblogs.com/webu/archive/2012/11/04/2753957.html

php多线程解决之stream_socket_client相关推荐

  1. 利用多线程解决多业务不同定时区间歇触发问题的一种方法

    利用多线程解决多业务不同定时区间歇触发问题的一种方法 参考文章: (1)利用多线程解决多业务不同定时区间歇触发问题的一种方法 (2)https://www.cnblogs.com/naaoveGIS/ ...

  2. java多线程解决应用挂死的问题

    java多线程解决应用挂死的问题 参考文章: (1)java多线程解决应用挂死的问题 (2)https://www.cnblogs.com/hushaojun/p/4323808.html (3)ht ...

  3. 多线程解决同步问题浅析

    多线程解决同步问题浅析 参考文章: (1)多线程解决同步问题浅析 (2)https://www.cnblogs.com/fengtangjiang/p/11103595.html 备忘一下.

  4. python(pyqt5)多线程解决界面无响应

    多线程解决界面无响应多线程解决界面无响应多线程解决界面无响应 def open_train_task():import osos.system(r"E:\kg\TURN-TAP-master ...

  5. python多线程解决数据安全问题

    python多线程解决数据安全问题 在使用多线程处理问题,可能会遇到以下情况,一个车站售卖100张车票,有三个窗口同时售卖,怎么保证票被卖出,该编号票显示已售卖,其他窗口只能售卖其他票, 遇到的问题: ...

  6. Springboot定时器多线程解决多个定时器冲突问题

    使用场景 : 我们的订单服务,一般会有一个待支付订单,而这个待支付订单是有时间限制的,比如阿里巴巴的订单是五天,淘宝订单是一天,拼多多订单是一天,美团订单是15分钟- 基金系统中,如何同时更新多个存储 ...

  7. JAVA多线程解决哲学家问题(GUI演示)

    利用JAVA多线程与Swing编程制作GUI演示哲学家问题解决 感谢出现在GUI中的我以及我的四位室友并且感谢他们为我的程序设计提供一部分灵感让该演示显得不那么单调. 问题描述: 由Dijkstra提 ...

  8. 创新实训-python爬虫多线程|解决中文乱码问题|卡片向上浮动效果|图文切换

    创新实训-python爬虫多线程|乱码问题|前端样式重新修改 考完毛概,把上周的工作总结一下.爬虫在第一周的时候只爬了一个就业指导这一个模块,这一次又加了招聘服务模块,所以就用了两个线程.前端首页一开 ...

  9. python协程(4): asyncio结合多线程解决阻塞问题以及timer模拟

    一.异步方法依然会假死(freezing) 什么是程序的假死,这里不再多描述,特别是在编写桌面程序的时候,如果是使用单个线程,同步函数的方式,假死是不可避免的,但是有时候我们即使是使用了异步函数的方式 ...

最新文章

  1. 生成批量缩率图_Windows系统实战之:批量生成某类型文件
  2. opencv 图像分割 阈值分割 图像二值化 灰度图
  3. Unity shader之金属质感衣服
  4. django 项目中遇到的问题(持续更新中)
  5. 无需代码绘制出的热力图,0基础小白也能3分钟上手
  6. Paddle实现NLP-文本分类
  7. Logism · 原码一位乘法器 实验
  8. OneDrive文件数限制:150000
  9. 网易2016在线笔试小结
  10. 串的模式匹配算法 ← BF算法
  11. 使用C++,用四阶Runge-Kutta的方法来求解一阶常微分方程
  12. 广义预测控制(GPC,含公式推导和仿真截图)
  13. 360和QQ之间的核战争!
  14. 单片机毕业设计 stm32智能电子秤系统设计与实现 - 物联网 嵌入式
  15. CNN卷积神经网络:花卉分类
  16. 2018汽车之家汽车品牌、车型数据库采集带品牌logo以及车型图
  17. archlinux安装-5-xfce4
  18. android 儿童 游戏,7-10岁儿童游戏大全
  19. 在ZF2中实现Zend Framework的Controller init/preDispatch/postDispatch方法
  20. tp6隐藏省略去掉url里的index.php路由前缀

热门文章

  1. StringBuffer
  2. c# winform程序调用托管dll(c#的dll),使用添加引用和动态加载dll
  3. 怎么用vnc访问自己内网电脑,同时又是同一个会话?
  4. Qt QString 中文 char* UTF-8 QByteArray QTextCodec unicode gb2312 GBK 乱码与转码问题
  5. 三极管共射、共集、共基分析及比较
  6. Kubernetes 容器编排
  7. 9.7 top:实时显示系统中各个进程的资源占用状况
  8. sjms-4 行为型模式
  9. 雷锋网独家解读:阿里云原生应用的布局与策略
  10. 函数计算帮助石墨文档突破性能瓶颈,有效节省服务器成本