温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

PHP长连接实现与使用方法的示例分析

发布时间:2021-06-03 11:34:29 来源:亿速云 阅读:252 作者:小新 栏目:开发技术

这篇文章给大家分享的是有关PHP长连接实现与使用方法的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。

本文实例讲述了PHP长连接实现与使用方法。分享给大家供大家参考,具体如下:

长连接技术(Long Polling)

服务器端hold住一个连接, 不立即返回, 直到有数据才返回, 这就是长连接技术的原理

长连接技术的关键在于hold住一个HTTP请求, 直到有新数据时才响应请求, 然后客户端再次自动发起长连接请求.

那怎么样hold住一个请求呢?服务器端的代码可能看起来像这样的

set_time_limit(0); //这句很重要, 不至于运行超时 while (true) {   if (hasNewMessage()) {     echo json_encode(getNewMessage());     break;   }   usleep(100000);   //避免太过频繁的查询 }

没错,就是通过循环来实现hold住一个请求, 不至于立即返回. 查询到有新数据之后才响应请求. 然后客户端处理数据后,再次发起长连接请求.

客户端的代码是像这样的

<script type="text/javascript">   (function longPolling() {     $.ajax({       'url': 'server.php',       'data': data,       'dataType': 'json',       'success': function(data) {         processData(data);         longPolling();       },       'error': function(data) {         longPolling();       }     });   })(); </script>

一个简易的聊天室

通过长连接, 我们可以开发一个简易的web聊天室

下面, 我们通过redis开发一个简易的web聊天室

1. 每一个客户端发起长连接时, 在服务器端生成一个消息队列, 对应该用户. 然后监听有无新数据, 有则返回数据到客户端进行处理, 并再起发起长连接请求.

2. 每一个客户端发起消息时, 进行消息队列的广播.

下面是代码片段:

<?php namespace church\LongPolling; use Closure; use church\LongPolling\Queue\RedisQueue; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\JsonResponse; class Server {   public $event = [];   public $redisQueue = null;   public $request = null;   public $response = null;   public function __construct()   {     $this->redisQueue = new RedisQueue();     $this->request = Request::createFromGlobals();     $this->response = new JsonResponse();   }   public function on($event, Closure $closure)   {     if (is_callable($closure)) {       $this->event[$event][] = $closure;     }   }   public function fire($event)   {     if (isset($this->event[$event])) {       foreach ($this->event[$event] as $callback) {         call_user_func($callback, $this);       }     }   }   public function sendMessage($data)   {     switch ($data['type']) {       case 'unicast':   //单播         $this->unicast($data['target'], $data['data'], $data['resource']);         break;       case 'multicast':    //组播         foreach ($data['target'] as $target) {           $this->unicast($target, $data['data'], $data['resource']);         }         break;       case 'broadcast':    //广播         foreach ($this->redisQueue->setQueueName('connections') as $target) {           $this->unicast($target, $data['data'], $data['resource']);         }         break;     }     $this->fire('message');   }   public function unicast($target, $message, $resource = 'system')   {     $redis_queue = new RedisQueue();     $redis_queue->setQueueName($target)->push($resource . ':' . $message);   }   public function getMessage($target)   {     return $this->redisQueue->setQueueName($target)->pop();   }   public function hasMessage($target)   {     return count($this->redisQueue->setQueueName($target));   }   public function run()   {     $data = $this->request->request;     while (true) {       if ($data->get('action') == 'getMessage') {         if ($this->hasMessage($data->get('target'))) {           $this->response->setData([             'state' => 'ok',             'message' => '获取成功',             'data' => $this->getMessage($data->get('target'))           ]);           $this->response->send();           break;         }       } elseif ($data->get('action') == 'connect') {         $exist = false;         foreach ($this->redisQueue->setQueueName('connections') as $connection) {           if ($connection == $data->get('data')) {             $exist = true;           }         }         if (! $exist) {           $this->redisQueue->setQueueName('connections')->push($data->get('data'));         }         $this->fire('connect');         break;       }       usleep(100000);     }   } }

长连接避免了过于频繁的轮询. 但服务器维持一个长连接也有额外的资源消耗. 大并发时性能不理想. 在小型应用里面可以考虑使用

更建议客户端使用html5的websocket协议, 服务器端使用swoole.

感谢各位的阅读!关于“PHP长连接实现与使用方法的示例分析”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

php
AI