서버 측에서 연결을 유지하고 즉시 반환하지 않습니다. 이것이 긴 연결 기술의 원칙입니다. 이 기사에서는 주로 PHP에서 긴 연결을 구현하는 방법을 공유하기를 바랍니다. 모두에게 도움이 될 수 있습니다.
장기 연결 기술의 핵심은 HTTP 요청을 보류하고 새 데이터가 있을 때까지 요청에 응답하지 않는 것입니다. 그러면 클라이언트가 자동으로 장기 연결 요청을 다시 시작합니다.
그렇다면 요청을 어떻게 보류합니까? 서버 측 코드는 다음과 같습니다.
set_time_limit(0); //这句很重要, 不至于运行超时while (true) 、{ if (hasNewMessage()) { echo json_encode(getNewMessage()); break; } usleep(100000); //避免太过频繁的查询}
예, 즉시 반환되지 않도록 요청을 보류하는 루프를 통해 구현됩니다. 그런 다음 새 데이터를 쿼리한 후에만 요청에 응답합니다. 클라이언트가 데이터를 처리하고 긴 연결 요청을 다시 시작합니다.
클라이언트 코드는 다음과 같습니다
<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>
긴 연결을 통해 간단한 웹 채팅방을 개발할 수 있습니다
다음으로 개발합니다. Redis를 통한 간단한 채팅방 웹 채팅방
각 클라이언트가 긴 연결을 시작하면 서버 측에 사용자에 해당하는 메시지 대기열이 생성됩니다. 그런 다음 새로운 데이터가 있는지 모니터링하고 데이터를 반환합니다. 처리를 위해 클라이언트에 연결을 요청하고 다시 긴 연결을 시작합니다.
각 클라이언트가 메시지를 시작하면 메시지 대기열이 브로드캐스트됩니다.
다음은 코드 조각입니다.
<?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); } } }
는 오픈 소스입니다. 소스 코드는 github
긴 연결을 기반으로 개발된 간단한 웹 버전입니다. 채팅방에서는 긴 연결을 사용하면 너무 빈번한 폴링을 피할 수 있습니다. 그러나 서버에서 긴 연결을 유지하는 것도 동시성이 큰 경우 성능이 이상적이지 않습니다. . 소규모 애플리케이션에 사용하는 것이 고려될 수 있습니다. 클라이언트는 html5 websocket 프로토콜을 사용하고 서버는 swoole을 사용하는 것이 더 좋습니다.
관련 권장 사항:
실현위 내용은 PHP는 긴 연결 방법을 구현합니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!