ホームページ  >  記事  >  バックエンド開発  >  PHPは長い接続メソッドを実装します

PHPは長い接続メソッドを実装します

小云云
小云云オリジナル
2018-03-21 11:50:004599ブラウズ

サーバー側で接続を保持し、データが存在するまでは戻りません。これが、PHP での長い接続の実装方法を主に説明するものです。みんなを助けることができる。

長時間接続テクノロジーの鍵は、HTTP リクエストを保持し、新しいデータが存在するまでリクエストに応答しないことです

では、どうやってリクエストを保持するのでしょうか?サーバー側のコードは次のようになります

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


はい、リクエストはすぐに返されないようにループを介して実装されています。その後、新しいデータがクエリされた後にのみ応答されます。クライアントはデータを処理し、再び長い接続リクエストを開始します

クライアント コードは次のとおりです

<script type="text/javascript">
    (function longPolling() {
        $.ajax({            &#39;url&#39;: &#39;server.php&#39;,            &#39;data&#39;: data,            &#39;dataType&#39;: &#39;json&#39;,            &#39;success&#39;: function(data) {
                processData(data);
                longPolling();
            },            &#39;error&#39;: 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[&#39;type&#39;]) {            case &#39;unicast&#39;:     //单播
                $this->unicast($data[&#39;target&#39;], $data[&#39;data&#39;], $data[&#39;resource&#39;]);                break;            case &#39;multicast&#39;:       //组播
                foreach ($data[&#39;target&#39;] as $target) {                    $this->unicast($target, $data[&#39;data&#39;], $data[&#39;resource&#39;]);
                }                break;            case &#39;broadcast&#39;:       //广播
                foreach ($this->redisQueue->setQueueName(&#39;connections&#39;) as $target) {                    $this->unicast($target, $data[&#39;data&#39;], $data[&#39;resource&#39;]);
                }                break;
        }        $this->fire(&#39;message&#39;);
    }    public function unicast($target, $message, $resource = &#39;system&#39;)
    {
        $redis_queue = new RedisQueue();        $redis_queue->setQueueName($target)->push($resource . &#39;:&#39; . $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(&#39;action&#39;) == &#39;getMessage&#39;) {                if ($this->hasMessage($data->get(&#39;target&#39;))) {                    $this->response->setData([                        &#39;state&#39; => &#39;ok&#39;,                        &#39;message&#39; => &#39;获取成功&#39;,                        &#39;data&#39; => $this->getMessage($data->get(&#39;target&#39;))
                    ]);                    $this->response->send();                    break;
                }
            } elseif ($data->get(&#39;action&#39;) == &#39;connect&#39;) {                $exist = false;                foreach ($this->redisQueue->setQueueName(&#39;connections&#39;) as $connection) {                    if ($connection == $data->get(&#39;data&#39;)) {                        $exist = true;
                    }
                }                if (! $exist) {                    $this->redisQueue->setQueueName(&#39;connections&#39;)->push($data->get(&#39;data&#39;));   
                }               
                $this->fire(&#39;connect&#39;);                break;
            }
            usleep(100000);
        }
    }
}

はオープンソース化しています。ソース コードは github に

長い接続に基づいて開発されたシンプルな Web バージョン チャット ルームでは、長い接続により頻繁なポーリングが回避されますが、サーバー上で長い接続を維持すると、追加のリソースも消費されます。同時実行数が多い場合、パフォーマンスは理想的ではありません。小規模な用途での使用が考えられます。クライアントでは html5 WebSocket プロトコルを使用し、サーバーでは swoole を使用することをお勧めします。

関連する推奨事項:

php ソケットで長い接続を実装する方法

長い http 接続と短い http 接続の原理の簡単な分析

PHPの中長期接続

の実現

以上がPHPは長い接続メソッドを実装しますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。