Home > Article > PHP Framework > How does workerman implement group chat?
#1. Basics
1. workerman
workerman is a conscientious and high-performance PHP socket server framework developed by Chinese people. It has more than 4K stars on gayHub, the world's largest same-sex dating platform. You can imagine how big it is. The cattle X. It can be deployed alone or integrated into MVC frameworks (TP, laravel, etc.). It can be said to be very practical and has good concurrency effects. Official website address: http://www.workerman.net/workermangayhub address: https://github.com/walkor /workerman/2. gateway-worker
gateway-worker (hereinafter referred to as gateway) is a TCP long connection framework developed based on workerman and is used to quickly develop TCP Long connection application. Online chat generally uses long connections to maintain communication. Although using workerman can achieve the same effect, gateway is more convenient and faster. (The chat room built by polling has been OUT, it is too...) gayhub address: https://github.com/walkor/GatewayWorker3. gatewayClient
gateClient is a component used to assist worker or gateway in grouping users and sending information to users. At the same time, it can quickly and easily convert the original The system uid and clientid are bound. gayhub address: https://github.com/walkor/GatewayClient2. Theory:
1. Principles of integration with the MVC system:
##·The existing mvc framework project and the independent deployment of GatewayWorker do not interfere with each other ;
##·All business logic is completed by post/get from the website page to the mvc framework;##·
GatewayWorker does not accept data from the client, that is, GatewayWorker does not process any business logic, and GatewayWorker is only used as a one-way push channel; ·
Only when the mvc framework needs to actively push data to the browser, the Gateway API (GatewayClient) is called in the mvc framework to complete the push. 2. Implementation steps:
(1) The website page establishes a websocket connection with GatewayWorker; (2) GatewayWorker finds that a page initiates a connection When, the client_id of the corresponding connection is sent to the website page;
(3) After the website page receives the client_id, it triggers an ajax request (assuming it is bind.php) and sends the client_id to the mvc backend;
(4) After mvc backend bind.php receives client_id, it uses GatewayClient to call Gateway::bindUid($client_id, $uid) to bind client_id to the current uid (user id or client unique identifier). If there is a group or group sending function, you can also use Gateway::joinGroup($client_id, $group_id) to add the client_id to the corresponding group;
(5) All requests initiated by the page are directly post/get to mvc The framework handles unified processing, including sending messages;
(6) When the mvc framework needs to send data to a certain uid or a certain group during business processing, directly call the GatewayClient interface Gateway::sendToUid Gateway::sendToGroup Just wait for it to be sent.
3. Implementation—Configuring and opening Gateway:
1. Download and use gateway
Can be used alone or placed in the public directory of the framework.
2. Edit start.php·
start.php needs to be run using the php command line. ·
Pay attention to the path of require_onceini_set('display_errors', 'on');
use Workerman\Worker;
if(strpos(strtolower(PHP_OS), 'win') === 0)
{
exit("start.php not support windows, please use start_for_win.bat\n");
}
// 检查扩展
if(!extension_loaded('pcntl'))
{
exit("Please install pcntl extension.See http://doc3.workerman.net/appendices/install-extension.html\n");
}
if(!extension_loaded('posix'))
{
exit("Please install posix extension.See http://doc3.workerman.net/appendices/install-extension.html\n");
}
// 标记是全局启动
define('GLOBAL_START', 1);
// 注意这里的路径
require_once '../vendor/autoload.php';
// 加载所有Applications/*/start.php,以便启动所有服务
foreach(glob(__DIR__.'/Applications/*/start*.php') as $start_file)
{
require_once $start_file;
}
// 运行所有服务
Worker::runAll();
3. start_gateway.php
·
Can be edited in ApplicationsYourAppstart_gateway.php// 部分文件内容
//将$gateway改成websocket协议,demo中是text协议
$gateway = new Gateway("websocket://0.0.0.0:8282");
4.start_register.php
·
It should be noted that $register in start_register.php must be text protocol, and the port must be noted // register 服务必须是text协议
$register = new Register('text://192.168.124.125:1238');
5. After configuration, open start.php
$ php start.php start
4. Implementation - Server Development
As mentioned above, the user only goes through the gateway's onConnect($client_id) when the connection is triggered, and all All business operations should be implemented in the web system. So I created a controller of GatewayServer.php to handle these businesses
<?php /** * Author: root * Date : 17-3-27 * time : 上午12:32 */ namespace app\index\controller; use GatewayClient\Gateway; use think\Cache; use think\Controller; use think\Request; use think\Session; class GatewayServer extends Controller { public function _initialize(){ } public function bind(Request $request) { // 用户连接websocket之后,绑定uid和clientid,同时进行分组,根据接收到的roomid进行分组操作 $userGuid=Session::get('loginuser'); $roomId=intval(trimAll($request->post('room'))); $clientId=trimAll($request->post('client_id')); // 接受到上面的三个参数,进行分组操作 Gateway::$registerAddress = '192.168.124.125:1238'; // client_id与uid绑定 // Gateway::bindUid($clientId, $userGuid); // 加入某个群组(可调用多次加入多个群组) 将clientid加入roomid分组中 Gateway::joinGroup($clientId, $roomId); // 返回ajax json信息 $dataArr=[ 'code'=>$userGuid, 'status'=>true, 'message'=>'Group Success' ]; return json()->data($dataArr); } // 接受用户的信息 并且发送 public function send(Request $request){ Gateway::$registerAddress = '192.168.124.125:1238'; // 获得数据 $userGuid=Session::get('loginuser'); $roomId=intval(trimAll($request->post('room'))); $message=trim($request->post('message')); // 获得用户的称呼 $userInfo=Cache::get($userGuid); // 将用户的昵称以及用户的message进行拼接 $nickname=$userInfo['nickname']; $message=$nickname." : ".$message; // 发送信息应当发送json数据,同时应该返回发送的用户的guid,用于客户端进行判断使用 $dataArr=json_encode(array( 'message' => $message, 'user'=>$userGuid )); // 向roomId的分组发送数据 Gateway::sendToGroup($roomId,$dataArr); } }
5. Implementation-Client connection and sending/receiving:
After opening the gateway, you can monitor and wait for the browser to access. The client uses js to monitor websocket here:
1. Used to handle client connection to websocket and receive messages// 这个示例和gateway官网的示例是一样的 // 监听端口 ws = new WebSocket("ws://192.168.124.125:8282"); // 绑定分组的ajaxURL var ajaxUrl="{:url('/gateway/bind')}"; // 发送消息的ajaxURL var ajaxMsgUrl="{:url('/gateway/send')}"; // 通过房间号进行分组 var roomId="{$roomInfo.guid}"; // 获取当前登录用户的guid,用于标识是自己发送的信息 var loginUser="{$userLoginInfo.guid}"; // 获取当前房间号的主播的uid,用于标识是主播发送的信息 var roomUser="{$roomInfo.uid}"; // 服务端主动推送消息时会触发这里的onmessage ws.onmessage = function(e){ // console.log(e.data); // json数据转换成js对象 var data = eval("("+e.data+")"); var type = data.type || ''; switch(type){ // Events.php中返回的init类型的消息,将client_id发给后台进行uid绑定 case 'init': // 利用jquery发起ajax请求,将client_id发给后端进行uid绑定 $.post(ajaxUrl, {client_id: data.client_id,room:roomId}, function(data){ // console.log(data); }, 'json'); break; // 当mvc框架调用GatewayClient发消息时直接alert出来 default : // 如果登陆用户的guid和数据发送者的guid一样,则使用不同的颜色(只能自己看到) if(loginUser == data.user){ addMsgToHtml(data.message,'#F37B1D'); break; // 如果发送者的guid和主播uid一样,则对所有的显示都增加一个[主播标识] }else if(data.user==roomUser){ addMsgToHtml("[主播] "+data.message,'#0e90d2'); break; }else{ // 其他的就正常发送消息 addMsgToHtml(data.message,'#333'); } break; } };
2. Used to add received messages to divs for display
// 向面板中增加新接收到的消息 // 其中message是消息,color是显示的颜色,主要为了区分主播以及自己发送的消息和系统提示 function addMsgToHtml(message,color) { if(message.length==0){ return false; } // 获取html,并且增加html var obj=$("#room-viedo-chat"); var html=obj.html(); // html+='<p><font color="'+color+'">'+message+'</p>'; obj.html(html); // 将滚动条滚动到底部 obj.scrollTop(obj[0].scrollHeight); }
3. Used to send messages
// 发送聊天消息 function sendMsg(){ // 去掉onclick属性,使得3秒之内无法发送信息 $("#sendMsgBox").attr('onclick',''); var btnObj=$("#sendMsgBtn"); var tmpNum=3; var tmpMsg=tmpNum+' S'; btnObj.text(tmpMsg); var int =setInterval(function () { // 3秒之内不能发送信息,3秒之后,回复onclick属性以及文字 if(tmpNum==0){ tmpMsg="发送"; clearInterval(int); btnObj.text("发送"); $("#sendMsgBox").attr('onclick','sendMsg()'); } btnObj.text(tmpMsg); tmpNum-=1; tmpMsg=tmpNum+' S'; },1000); var message=$("#chattext").val().trim(); var obj=$("#room-viedo-chat"); var html=obj.html(); if(message.length>=140){ // 获取html,并且增加html addMsgToHtml("系统提示: 不能超过140个字符","#8b0000"); return false; } if(message.length==0){ // 获取html,并且增加html addMsgToHtml("系统提示: 不能发送空消息","#8b0000"); return false; } // 向server端发送ajax请求 $.post(ajaxMsgUrl,{room:roomId,message:message},function (data) { },'json'); return false; }
4. A little html Code
<!--chat box start --> <div class=" am-u-md-12 am-u-lg-12 room-viedo-chat" id="room-viedo-chat" style="font-size:14px;"> </div> <div class="am-u-md-12 am-u-lg-12 room-viedo-chat-button-box"> <div class="left-div"> <textarea name="chattext" id="chattext" placeholder="输入聊天内容..."></textarea> </div> <div class="am-btn am-btn-default right-div am-text-center"onclick="sendMsg();"id="sendMsgBox"> <span class="" id="sendMsgBtn"> 发送 </span> </div> </div> <!--chat box end -->
六、效果:
效果很明显:
·系统提示是单独的颜色
·本人发布的,是自己能够分辨的橙色
·主播发布的是蓝色,同时前面有[主播]标识
·看其他人发布的就是普通的颜色
PHP中文网,有大量免费的workerman入门教程,欢迎大家学习!
The above is the detailed content of How does workerman implement group chat?. For more information, please follow other related articles on the PHP Chinese website!