Swoole and thinkp5 develop WebSocket online chat communication system



To use Swoole in ThinkPHP, you need to install the think Swoole composer package, provided that the system has installed the Swoole PECL extension*

To install think swoole, execute the composer command in the project root directory of tp5:

composer require topthink/think-swoole

 

If you don't say much, go straight to the code:

New WebSocket.php controller

(to confirm that the server is allowed to listen to the port, you need to add security group rules in pagoda environment.)

 1 <?php
 2  
 3 namespace app\home\controller;
 4 use think\swoole\Server;
 5 class WebSocket extends Server
 6 {
 7     protected $host = '0.0.0.0'; //Listen to all addresses
 8     protected $port = 9501; //Listen to port 9501
 9     protected $serverType = 'socket';
10     protected $option = [ 
11         'worker_num'=> 4, //Set up started Worker Process number
12         'daemonize'    => false, //Daemonization (online changed to true)
13         'backlog'    => 128, //Listen queue length
14         'dispatch_mode' => 2, //Fixed mode to ensure that data sent from the same connection will only be sent to the same worker Handle
15  
16         //Heartbeat detection: traverse all connections every 60 seconds, and forcibly close the connection without sending any data to the server within 10 minutes
17         'heartbeat_check_interval' => 60,
18         'heartbeat_idle_time' => 600
19     ];
20  
21     //Callback function when establishing connection
22     public function onOpen($server,$req)
23     {
24         $fd = $req->fd;//Client identity
25         $uid = $req->get['uid'];//Users delivered by the client id
26         $token = $req->get['token'];//User login delivered by client token
27         
28         //Omit token validation logic
29         if (!$token) {
30             $arr = array('status'=>2,'message'=>'token Expired');
31             $server->push($fd, json_encode($arr));
32             $server->close($fd);
33             return;
34         }
35         //Omit binding to user fd logic......
36         echo "user{$uid}Connection established,Identified as{$fd}\n";
37     }
38  
39     //Callback function when receiving data
40     public function onMessage($server,$frame)
41     {
42         $fd = $frame->fd;
43         $message = $frame->data;
44  
45         //Omission through fd Query users uid logic......
46         $uid = 666;
47         $data['uid'] = $uid;
48         $data['message'] = 'user'.$uid.'Sent:'.$message;
49         $data['post_time'] = date("m/d H:i",time());
50         $arr = array('status'=>1,'message'=>'success','data'=>$data);
51  
52         //Push to current connected users only
53         //$server->push($fd, json_encode($arr));
54         
55         //Push to all connected users
56         foreach($server->connections as $fd) {
57             $server->push($fd, json_encode($arr));
58         } 
59     }
60  
61     //Callback function when connection is closed
62     public function onClose($server,$fd)
63     {
64         echo "Identification{$fd}Connection closed\n";
65     }
66 }

 

Front end demo page:

(omit the logic of the controller to judge the login status and allocate data...)

 

  1 <!DOCTYPE html>
  2 <html lang="en">
  3 <head>
  4 <meta charset="UTF-8" />
  5 <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
  6 <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
  7 <title>Chat</title>
  8 <link rel="stylesheet" type="text/css" href="/static/liaotian/chat.css" />
  9 <script src="/static/liaotian/js/jquery.min.js"></script>
 10 <script src="/static/liaotian/js/flexible.js"></script>
 11 </head>
 12 <body>
 13     <header class="header">
 14         <a class="back" href="javascript:history.back()"></a>
 15         <h5 class="tit">chat online</h5>
 16         <a href=""><div class="right">Sign out</div></a>
 17     </header>
 18  
 19     <!-- Chat content start-->
 20     <div class="message"> </div>
 21     <!-- Chat content end-->
 22  
 23     <!-- bottom start-->
 24     <div class="footer">
 25         <img id="setbtn" src="/static/liaotian/images/hua.png" alt="" />
 26         <img src="/static/liaotian/images/xiaolian.png" alt="" />
 27         <input type="text" id="msg" value="" maxlength="300">
 28         <p style="background: rgb(17, 79, 142);" id="sendBtn">Send out</p>
 29     </div>
 30     <!-- bottom end-->
 31 </body>
 32 </html>
 33 <script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
 34 <script src="https://cdn.bootcss.com/layer/3.1.0/layer.js"></script>
 35 <script type="text/javascript">
 36 $(function () {
 37     var uid = 666;//Current user id
 38     var token = 'abcdefg';//user token
 39  
 40     //Determine whether the browser supports WebSocket
 41     var supportsWebSockets = 'WebSocket' in window || 'MozWebSocket' in window;
 42     if (supportsWebSockets) {
 43         //establish WebSocket Connection ( ip Change address to own host ip)
 44         var ws = new WebSocket("ws://127.0.0.1:9501?uid="+uid+"&token="+token);
 45         ws.onopen = function () {
 46             layer.msg('Server connection successful',{shade:0.1,icon:1,time:600});
 47         };
 48         ws.onerror = function () {
 49             layer.msg('Server connection failed',{shade:0.1,icon:2,time:600});
 50         };
 51         ws.onmessage = function (evt) {
 52             var data = $.parseJSON(evt.data);
 53             //Error prompt
 54             if(data.status != 1){
 55                 layer.alert(data.message,{icon:2});
 56                 return;
 57             }
 58             //Message return
 59             if (data.status==1 && data.data.message!='') {
 60                 var html = "";
 61                 if (data.data.uid == uid) {
 62                     html += "<div style='word-break:break-all' class=\"show\"><div class=\"time\">"+data.data.post_time+"</div><div class=\"msg\"><img src=\""+data.data.head_img+"\" alt=\"\" /><p><i clas=\"msg_input\"></i>"+data.data.message+"</p></div></div>";
 63                 }else{
 64                     html += "<div style='word-break:break-all' class=\"send\"><div class=\"time\">"+data.data.post_time+"</div><div class=\"msg\"><img src=\""+data.data.head_img+"\" alt=\"\" /><p><i clas=\"msg_input\"></i>"+data.data.message+"</p></div></div>";
 65                 }
 66             }
 67             $(".message").append(html);
 68             setTimeout(function () {
 69                 ($('.message').children("div:last-child")[0]).scrollIntoView();//scroll up
 70             },100);
 71         };
 72         ws.onclose = function (res) {
 73             
 74         };
 75         //Push button to send
 76         $("#sendBtn").click(function () {
 77             var contents = $("#msg").val().trim();
 78             if(contents == null || contents == ""){
 79                 layer.msg('Content is empty',{shade:0.1,icon:2,time:600});            
 80                 return false;
 81             }else{
 82                 ws.send(contents);
 83                 $("#msg").val("");
 84             }
 85         });
 86         //Carriage return
 87         $("#msg").keydown(function (evel) {
 88             var that = $(this);
 89             if (evel.keyCode == 13) {
 90                 evel.cancelBubble = true;
 91                 evel.preventDefault();
 92                 evel.stopPropagation();
 93                 var contents = that.val().trim();
 94                 if(contents == null || contents == ""){
 95                     layer.msg('Content is empty',{shade:0.1,icon:2,time:600});              
 96                     return false;
 97                 }else{
 98                     ws.send(contents);
 99                     that.val("");
100                 }
101             }
102         });
103     }else{
104         layer.alert("Your browser does not support WebSocket!");
105     }
106 });
107 </script>
108  

 

Move the server to the project root directory to start the service:

php public/index.php Websocket/start

 

The path here is because I bound the home module as the default module. The default situation of tp5 is: php public/index.php index/Websocket/start)

 

Open successfully. Check whether the port has been monitored:

lsof -i:9501

 

Tags: PHP JQuery Javascript socket

Posted on Mon, 04 Nov 2019 09:58:41 -0500 by tecktalkcm0391