连接巧妙解决PHP无法实现多线程的问题

php多线程  时间:2021-01-31  阅读:()

巧妙解决P HP无法实现多线程的问题

有没有办法在PHP中实现多线程呢假设你正在写一个基于多台服务器的PHP应用理想的情况时同时向多台服务器发送请求而不是一台接一台。可以实现吗当有人想要实现并发功能时他们通常会想到用fo rk或者s pawn threa ds但是当他们发现PHP不支持多线程的时候大概会转换思路去用一些不够好的语言 比如Per l。

其实的是大多数情况下你大可不必使用for k或者线程并且你会得到比用fo rk或th read更好的性能。假设你要建立一个服务来检查正在运行的n台服务器 以确定他们还在正常运转。你可能会写下面这样的代码

1. $hosts = array("host1 .sample.com", "host2 .sample.com", "host3.sampl e.com") ;

2. $timeout = 15;

3. $status = array( ) ;

4. foreach ($hosts as $host) {

5. $errno = 0;

6. $errstr = "";

7. $s = fsockopen($host, 80, $errno, $errstr, $timeout) ;

8. if ($s) {

9. $status[$host] = "Connectedn";

10. fwrite($s, "HEAD / HTTP/1.0rnHost: $hostrnrn") ;

11. do {

12. $data = fread($s, 8192) ;

13. if (strlen($data) == 0) {

14. break;

15. }

16. $status[$host] .= $data;

17. }

18. while (true) ;

19. fclose($s) ;

20. }

21. else {

22. $status [$host] = "Connection failed: $errno $errstrn";

23. }

24. }

25.print_r($status) ;

26. ?>

它运行的很好但是在fs ockop en()分析完ho stnam e并且建立一个成功的连接或者延时$timeo ut秒之前扩充这段代码来管理大量服务器将耗费很长时间。

因此我们必须放弃这段代码我们可以建立异步连接-不需要等待fsock open返回连接状态。PHP仍然需要解析h ostna me 所以直接使用ip更加明智 不过将在打开一个连接之后立刻返回继而我们就可以连接下一台服务器。

有两种方法可以实现 PHP5中可以使用新增的str eam_s ocket_clie nt()函数直接替换掉fso cketo pen() 。PHP5之前的版本你需要自己动手用sock ets扩展解决问题。下面是PH P5中的解决方法

1. $hosts = array("host1 .sample.com", "host2 .sample.com", "host3.sampl e.com") ;

2. $timeout = 15;

3. $status = array( ) ;

4. $sockets = array( ) ;

5. /* Initiate connections to all the hosts simultaneously */

6. foreach ($hosts as $id => $host) {

7. $s = stream_socket_client("$host: 80", $errno, $errstr, $timeout,

8. STREAM_CLIENT_ASYNC_CONNECT| STREAM_CLIENT_CONNECT) ;

9. if ($s) {

10. $sockets[$id] = $s;

11. $status[$id] = "in progress";

12. }

13. else { $status[$id] = "failed, $errno $errstr";

14. }

15. }

16. /* Now, wait for the results to come back in */

17.

18.while (count($sockets) ) {

19. $read = $write = $sockets;

20. /* This is the magic function - explained below */

21. $n = stream_select($read, $write, $e = null, $timeout) ;

22. if ($n > 0) {

23. /* readable sockets either have data for us, or are failed * connection attempts */

24. foreach ($read as $r) {

25. $id = array_search($r, $sockets) ;

26. $data = fread($r, 8192) ;

27. if (strlen($data) == 0) {

28. if ($status[$id] == "in progress") {

29. $status[$id] = "failed to connect";

30. }

31. fclose($r) ;

32. unset($sockets[$id] ) ;

33. }

34. else {

35. $status[$id] .= $data;

36. }

37. }

38. /* writeable sockets can accept an HTTP request */

39. foreach ($write as $w) {

40. $id = array_search($w, $sockets) ;

41. fwrite($w, "HEAD / HTTP/1.0rnHost: "

42. . $hosts [$id] . "rnrn") ;

43. $status[$id] = "waiting for response";

44. }

45. }

46. else {

47. /* timed out waiting; assume that all hosts associated * with $sockets are faulty */

48. foreach ($sockets as $id => $s) {

49. $status[$id] = "timed out "

50. . $status[$id] ;

51. }

52.break;

53. }

54. }

55. foreach ($hosts as $id => $host) {

56. echo "Host: $hostn"; echo "Status: "

57. . $status[$id] . "nn";

58. }

59. ?>

我们用st ream_selec t()等待soc kets打开的连接事件。 strea m_sel ect()调用系统的selec t(2)函数来工作前面三个参数是你要使用的str eams的数组你可以对其读取写入和获取异常分别针对三个参数 。 stream_sel ect()可以通过设置$timeout 秒参数来等待事件发生-事件发生时相应的sockets数据将写入你传入的参数。

下面是PH P4. 1.0之后版本的实现如果你已经在编译PH P时包含了socke ts(ext/socke ts)支持你可以使用根上面类似的代码只是需要将上面的st reams/files ystem函数的功能用ext/socke ts函数实现。主要的不同在于我们用下面的函数代替stream_soc ket_c lient ()来建立连接

1. // This value is correct for Linux, other systems have other values

2. define( 'EINPROGRES S' , 115) ;

3. function non_blocking_connect($host, $port, &$errno, &$errstr, $timeout) {

4. $ip = gethostbyname($host) ;

5. $s = socket_create(AF_INET, SOCK_STREAM, 0) ;

6. if (socket_set_nonblock($s) ) {

7. $r = @socket_connect($s, $ip, $port) ;

8. if ($r | | socket_last_error( ) == EINPROGRESS) {

9. $errno = EINPROGRES S;

10. return $s;

11. }

12. }

13. $errno = socket_last_error($s) ;

14. $errstr = socket_strerror($errno) ;

15. socket_close($s) ;

16. return false;

17. }

18. ?>

现在用so cket_selec t()替换掉st ream_selec t() 用sock et_re ad()替换掉fr ead() 用sock et_wr ite()替换掉fwrite() 用sock et_cl ose()替换掉fc lose()就可以执行脚本了

PHP5的先进之处在于你可以用s tream_sele ct()处理几乎所有的str eam。例如你可以通过inc lude STDIN用它接收键盘输入并保存进数组你还可以接收通过pr oc_op en()打开的管道中的数据。

提速啦(900元/月),杭州BGP E5-2665/89*2 32核 48G 100G防御

提速啦的来历提速啦是 网站 本着“良心 便宜 稳定”的初衷 为小白用户避免被坑提速啦的市场定位提速啦主要代理市场稳定速度的云服务器产品,避免新手购买云服务器的时候众多商家不知道如何选择,妮妮云就帮你选择好了产品,无需承担购买风险,不用担心出现被跑路 被诈骗的情况。提速啦的售后保证提速啦退款 通过于合作商的友好协商,云服务器提供3天内全额退款,超过3天不退款 物理机部分支持当天全额退款提速啦提现 充...

Hostodo:$19.99/年KVM-1GB/12GB/4TB/拉斯维加斯

Hostodo发布了几款采用NVMe磁盘的促销套餐,从512MB内存起,最低年付14.99美元,基于KVM架构,开设在拉斯维加斯机房。这是一家成立于2014年的国外VPS主机商,主打低价VPS套餐且年付为主,基于OpenVZ和KVM架构,产品性能一般,数据中心目前在拉斯维加斯和迈阿密,支持使用PayPal或者支付宝等付款方式。下面列出几款NVMe硬盘套餐配置信息。CPU:1core内存:512MB...

Hostodo(年付$34.99), 8TB月流量 3个机房可选

Hostodo 算是比较小众的海外主机商,这次九月份开学季有提供促销活动。不过如果我们有熟悉的朋友应该知道,这个服务商家也是比较时间久的,而且商家推进活动比较稳,每个月都有部分活动。目前有提供机房可选斯波坎、拉斯维加斯和迈阿密。从机房的地理位置和实际的速度,中文业务速度应该不是优化直连的,但是有需要海外业务的话一般有人选择。以前一直也持有他们家的年付12美元的机器,后来用不到就取消未续约。第一、开...

php多线程为你推荐
盗版win8.1升级win10安装盗版windows10系统后怎么安装正版月付百万的女人们既然男人大都觉得下体毛发多的女人比较性感..那为什么那些特殊职业的女人们大多把下体的毛脱掉呢..?骁龙750g和765g哪个好麒麟970跟骁龙730哪个更好电脑管家和360哪个好360卫士和电脑管家,哪个更好苹果手机助手哪个好苹果手机助手哪个好用些谁知道无纺布和熔喷布口罩哪个好大雾天气带什么样的口罩最好海克斯皮肤哪个好摄魂使者薇恩和海克斯安妮皮肤哪个好 怎么合成车险哪个好人保和平安车险哪个好云盘哪个好免费的网盘哪个好用啊?飞信空间登录移动飞信客户端怎么登陆???
域名转让网 美国vps 如何注册中文域名 西安服务器 duniu oneasiahost lamp配置 一点优惠网 长沙服务器 服务器维护方案 admit的用法 银盘服务是什么 卡巴斯基免费试用版 申请网站 宏讯 沈阳主机托管 监控服务器 攻击服务器 asp空间 碳云 更多