使用workerman搭建即时聊天

Posted zrn-php

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用workerman搭建即时聊天相关的知识,希望对你有一定的参考价值。

开发文档:http://doc2.workerman.net/

下载服务器端安装文件:

技术图片

 

 

 有windows版和linux版两个版本,我下载的linux版,在windows上也可以运行。

打开后有这些文件:

技术图片

把这个文件放在服务器上或者项目中都可以,需要运行的就是最后一个start_for_win.bat文件。

技术图片

 

 

 运行成功。

修改start_gateway.php文件:

 1 <?php 
 2 /**
 3  * This file is part of workerman.
 4  *
 5  * Licensed under The MIT License
 6  * For full copyright and license information, please see the MIT-LICENSE.txt
 7  * Redistributions of files must retain the above copyright notice.
 8  *
 9  * @author walkor<walkor@workerman.net>
10  * @copyright walkor<walkor@workerman.net>
11  * @link http://www.workerman.net/
12  * @license http://www.opensource.org/licenses/mit-license.php MIT License
13  */
14 use WorkermanWorker;
15 use WorkermanWebServer;
16 use GatewayWorkerGateway;
17 use GatewayWorkerBusinessWorker;
18 use WorkermanAutoloader;
19 
20 // 自动加载类
21 require_once __DIR__ . ‘/../../vendor/autoload.php‘;
22 
23 // gateway 进程,这里使用Text协议,可以用telnet测试
24 $gateway = new Gateway("websocket://0.0.0.0:8282");
25 // gateway名称,status方便查看
26 $gateway->name = ‘YourAppGateway‘;
27 // gateway进程数
28 $gateway->count = 4;
29 // 本机ip,分布式部署时使用内网ip
30 $gateway->lanIp = ‘127.0.0.1‘;
31 // 内部通讯起始端口,假如$gateway->count=4,起始端口为4000
32 // 则一般会使用4000 4001 4002 4003 4个端口作为内部通讯端口 
33 $gateway->startPort = 2900;
34 // 服务注册地址
35 $gateway->registerAddress = ‘127.0.0.1:1238‘;
36 
37 // 心跳间隔
38 $gateway->pingInterval = 60;
39 // 心跳数据
40 $gateway->pingData = ‘{"type":"ping"}‘;
41 
42 /* 
43 // 当客户端连接上来时,设置连接的onWebSocketConnect,即在websocket握手时的回调
44 $gateway->onConnect = function($connection)
45 {
46     $connection->onWebSocketConnect = function($connection , $http_header)
47     {
48         // 可以在这里判断连接来源是否合法,不合法就关掉连接
49         // $_SERVER[‘HTTP_ORIGIN‘]标识来自哪个站点的页面发起的websocket链接
50         if($_SERVER[‘HTTP_ORIGIN‘] != ‘http://kedou.workerman.net‘)
51         {
52             $connection->close();
53         }
54         // onWebSocketConnect 里面$_GET $_SERVER是可用的
55         // var_dump($_GET, $_SERVER);
56     };
57 }; 
58 */
59 
60 // 如果不是在根目录启动,则运行runAll方法
61 if(!defined(‘GLOBAL_START‘))
62 {
63     Worker::runAll();
64 }

第24行,把tcp协议改为websocket协议;

第38行和40行,设置服务器向客户端发送的心跳时间,检测客户端是否连接,未连接将会断开。

下面的内容都是默认注释掉的,根据自己的需要打开或者修改。

再次运行start_for_win.bat文件:

技术图片

 

 协议就变为websocket协议了,现在就可以做项目内的操作了。

 

还需要再下载一个文件:https://github.com/walkor/GatewayClient

技术图片

 

 

 把这几个文件放进thinkphp的extend文件夹下(我用的是thinkphp5.0版本):

技术图片

 

 

 在Gateway.php的文件中方法几乎都写好了。

写了一个简单的前端页面:

技术图片

 

 1 <!DOCTYPE html>
 2 <html lang="zh">
 3     <head>
 4         <meta charset="UTF-8">
 5         <meta name="viewport" content="width=device-width, initial-scale=1.0">
 6         <meta http-equiv="X-UA-Compatible" content="ie=edge">
 7         <title></title>
 8     </head>
 9     <body>
10         <ul id="msgUl">
11             <li>ws://127.0.0.1:8282</li>
12         </ul>
13         <input type="" name="" id="sendValue" value="" />
14         <button type="button" id="sendButton">发送</button>
15 
16         <div style="margin-top: 100px">
17             {volist name="msg" id="vo" empty="这里没有数据" key =‘s‘}
18                     <br/>
19                 <span>{$vo.user_name}:</span>
20                 <span>{$vo.msg}</span>
21                 <span>{$vo.createtime}</span>
22                     <br/>
23               {/volist}
24         </div>
25 
26         <script src="http://www.zhihuapinpai.com/static/index/js/jquery-1.11.3.min.js"></script>
27         <script>
28             // var ws = new WebSocket("ws://123.56.216.232:8282");
29             var ws = new WebSocket("ws://127.0.0.1:8282");
30 
31             ws.onopen = function() {
32                 $(#msgUl).append(<li>已连接上...</li>)
33                 sendValue();
34             };
35 
36             ws.onmessage = function(evt) {
37                 $(#msgUl).append(<li>接收到: + evt.data + </li>)
38                 var obj = JSON.parse(evt.data);
39                 if (obj.type == onConnect) {
40                     // 连接成功
41                     $(#msgUl).append(<li>client_id: + obj.client_id + </li>)
42                     $.ajax({
43                         type:"POST",
44                         url:"/index.php/api/Index/user_bind",
45                         data:{
46                             client_id:obj.client_id
47                         },
48                         dataType: "html",
49                         success: function(data){
50                             console.log(成功)
51                         }
52                     });
53                 } else if (obj.type == ping) {
54                     // 心跳检测 不做任何处理
55                 } else if (obj.type == chatGroup) {
56                     // 群组聊天
57                     $(#msgUl).append(<li>接收到: + evt.data + </li>)
58                 }
59             };
60 
61             ws.onclose = function() {
62                 // console.log(‘连接已关闭...‘);
63                 $(#msgUl).append(<li>连接已关闭...</li>)
64             };
65 
66             function sendValue() {
67                 $(#sendButton).click(function() {
68                     var thisValue = $(#sendValue).val();
69                     if (thisValue) {
70                         ws.send(thisValue);
71                         $(#msgUl).append(<li>发送数据: + thisValue + </li>)
72                         $.get("/index.php/api/Index/send_msg/msg/"+thisValue,function (data,status) {
73                             console.log(成功:+thisValue)
74                         });
75                     }
76                 })
77             }
78         </script>
79     </body>
80 </html>

 第42—52行把client_id传到后台,与用户表中用户进行绑定。

后台代码:

 1 <?php
 2 namespace appapicontroller;
 3 use thinkController;
 4 use GatewayClientGateway;
 5 use thinkDb;
 6 
 7 
 8 class Index extends Controller
 9 {
10 
11     public function websocket(){
12         $where=[];
13         $user_id=1;
14         $where[‘from_id|to_id‘]=$user_id;
15         $msg=Db::name(‘msg‘)->where($where)->select();
16         foreach ($msg as $key=>$val){
17             $msg[$key][‘createtime‘]=date(‘Y-m-d H:i:s‘,$val[‘createtime‘]);
18             $msg[$key][‘user_name‘]=Db::name(‘user‘)->where([‘id‘=>$val[‘from_id‘]])->value(‘name‘);
19         }
20         $this->assign(‘msg‘,$msg);
21         return view();
22     }
23 
24     //绑定用户
25     public function user_bind($user_id=1){
26         //$user_id=1; //发送人用户id
27         $client_id = input(‘post.client_id‘);
28 //        $user=Db::name(‘user‘)->where([‘id‘=>$user_id])->find();
29         Gateway::bindUid($client_id, 1);
30         return $client_id;
31     }
32 
33     //发送信息
34     public function send_msg(){
35         $msg=input(‘msg‘);
36         if($msg){
37             $data=[
38               ‘msg‘=>$msg,
39               ‘from_id‘=>1,
40               ‘to_id‘=>2,
41               ‘createtime‘=>time()
42             ];
43             Db::name(‘msg‘)->insert($data);
44             Gateway::sendToUid(1,$msg);
45             Gateway::sendToUid(2,$msg);
46         }
47         return ‘success‘;
48     }
49 
50 }

发送消息存入数据库,页面显示即可。

技术图片

 

 

以上是关于使用workerman搭建即时聊天的主要内容,如果未能解决你的问题,请参考以下文章

使用GatewayWorker 开发个即时聊天demo

使用nssm部署windows服务启动应用

即时聊天软件的原理,Web网页的聊天又是怎么实现的呢?

使用workerman实现在线聊天-第一版

如何用gslauncher搭建直播系统

F1 workerman 介绍及项目环境搭建