PHP persistent connection implementation and usage
This article describes how to implement and use PHP persistent connections. We will share this with you for your reference. The details are as follows:
Long Polling)
Hold a connection on the server and do not return immediately until there is data. This is the principle of persistent connection technology.
The key to persistent connection technology is to hold an HTTP request and respond to the request only when new data is available. Then, the client automatically initiates a persistent connection request again.
How can we hold a request? The server code may look like this
Set_time_limit (0); // This sentence is very important and will not run timeout while (true) {if (hasNewMessage () {echo json_encode (getNewMessage (); break ;} usleep (100000); // avoid too frequent queries}
Yes, it means to hold a request through a loop, so that the request will not be returned immediately. The request will be returned only after new data is queried. After the client processes the data, it will initiate a persistent connection request again.
The client code is like this
<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>
A Simple Chat Room
Through persistent connections, we can develop a simple web chat room
Below, we develop a simple web chat room through redis
1. when each client initiates a persistent connection, a message queue is generated on the server. then listen for new data. If yes, return data to the client for processing and initiate a persistent connection request.
2. Each client broadcasts a message queue when initiating a message.
The following is a code snippet:
<? Phpnamespace 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: createFromGlobal S (); $ 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 ': // unicast $ this -> Unicast ($ data ['target'], $ data ['data'], $ data ['resource']); break; case 'multicast ': // multicast foreach ($ data ['target'] as $ target) {$ this-> unicast ($ target, $ data ['data'], $ data ['resource']);} break; case 'broadcast': // broadcast foreach ($ this-> redisQueue-> setQueueName ('ons ons') as $ target) {$ this-> unicast ($ target, $ data ['data'], $ data ['resource']);} break ;} $ this-> fire ('message');} public funct Ion 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' => 'obtained successfully ', 'data' => $ this-> getMessage ($ data-> get ('target')]); $ this-> response-> send (); break ;}} elseif ($ data-> get ('action') = 'connect ') {$ exist = false; foreach ($ this-> redisQueue-> setQueueName ('connections ') as $ connecti On) {if ($ connection = $ data-> get ('data') {$ exist = true ;}} if (! $ Exist) {$ this-> redisQueue-> setQueueName ('connections')-> push ($ data-> get ('data '));} $ this-> fire ('connect '); break;} usleep (100000 );}}}
Persistent connections avoid too frequent round-robin. However, when the server maintains a persistent connection, additional resources are consumed. High concurrency may cause unsatisfactory performance. You can consider using this method in small applications.
We recommend that the client use the html5 websocket protocol and the server use swoole.
For swoole, you can view the official website: https://www.swoole.com/