>  기사  >  백엔드 개발  >  PHP 긴 연결 사용 사례 분석

PHP 긴 연결 사용 사례 분석

php中世界最好的语言
php中世界最好的语言원래의
2018-05-18 14:48:492183검색

이번에는 PHP 장기 연결 사용 사례 분석을 가져오겠습니다. PHP 장기 연결 사용 시 주의사항은 무엇인가요?

Long Polling

서버 측에서 연결을 유지하고 데이터가 있을 때까지 즉시 반환하지 않습니다. 이것이 긴 연결 기술의 원칙입니다.

긴 연결 기술의 핵심은 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 웹 채팅방을 통해 간단한 채팅방을 개발하세요

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 웹소켓 프로토콜을 사용하는 것이 좋습니다. 서버측에서는 swoole을 사용합니다.

이 기사의 사례를 읽으신 후 방법을 마스터하셨다고 생각합니다. PHP 중국어 웹사이트의 다른 관련 기사도 주목해 주세요!

추천 도서:

PHP 네임스페이스 사용에 대한 자세한 설명


PHP 중국어 도구 클래스 ChineseUtil을 사용하여 한자와 병음을 변환하는 방법 ChineseUtil

위 내용은 PHP 긴 연결 사용 사례 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.