初衷:本来想学习Workerman的流程,但是发现GatewayWorker已经把Workerman的一些东西:长连接、心跳、聊天等封装好了,所以先来学习一下GatewayWorker。
注意:此篇教程只是做了点对点通信(也就是一对一聊天),但是里面有第三者可以跟前面两个进行通信,也就是说得等第二篇教程出来;记住每次修改GatewayWorker的events文件后都要重新启动服务。
一、GatewayWorker下载地址及手册
1.下载地址:https://www.workerman.net/download 或者 https://github.com/walkor/gatewayworker
2.手册地址:http://doc2.workerman.net/
二、Tp5的手册及下载地址
1.自己百度去,tp都不会还搞什么聊天系统!!!
三、涉及到的知识点
1.Gateway::sendToAll('string'); // 给所有用户发送数据
2.Gateway::sendToClient($client_id,'string'); // 给某一个客户端发送数据
3.Gateway::bindUid($client_id, $uid); // 绑定自有系统的用户id
4.Gateway::sendToUid($uid, 'string'); // 给系统某一个用户id发送数据
5.onConnect(); // GatewayWorker中自带的方法:客户端与服务器连接
6.onMessage(); // GatewayWorker中自带的方法:客户端与服务器通信
7.onClose(); // GatewayWorker中自带的方法:客户端与服务器断开连接
8.var ws = new WebSocket("ws://xx.xx.xx.xx:8256"); // 前端js里面实例化一个WebSocket
9.ws.onmessage = function(e){······}; // WebSocket 接收服务器返回的信息,然后做进一步处理
10.ws.send(string); // WebSocket 向服务器发送数据
11.eval('(' +json+ ')'); // js中eval()函数,把json转换成object
四、具体实现方法
1.tp5的indexController
<?php
namespace app\index\controller;
use think\Controller;
class Index extends Controller
{
public function index()
{
$formId = input('from_id');
$toId = input('to_id');
$this->assign('from_id', $formId);
$this->assign('to_id', $toId);
return $this->fetch();
}
}
2.GatewayWorker中的events文件
<?php
/**
* This file is part of workerman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**
* 用于检测业务代码死循环或者长时间阻塞等问题
* 如果发现业务卡死,可以将下面declare打开(去掉//注释),并执行php start.php reload
* 然后观察一段时间workerman.log看是否有process_timeout异常
*/
//declare(ticks=1);
use \GatewayWorker\Lib\Gateway;
/**
* 主逻辑
* 主要是处理 onConnect onMessage onClose 三个方法
* onConnect 和 onClose 如果不需要可以不用实现并删除
*/
class Events
{
/**
* 当客户端连接时触发
* 如果业务不需此回调可以删除onConnect
*
* @param int $client_id 连接id
*/
public static function onConnect($client_id)
{
// 向当前client_id发送数据
// Gateway::sendToClient($client_id, "Hello $client_id\r\n");
// // 向所有人发送
// Gateway::sendToAll("$client_id login\r\n");
// 打开页面请求,发送init绑定uid
$data = [
'type' => 'init',
];
Gateway::sendToClient($client_id, json_encode($data));
}
/**
* 当客户端发来消息时触发
* @param int $client_id 连接id
* @param mixed $message 具体消息
*/
public static function onMessage($client_id, $message)
{
$data = json_decode($message, true);
if (!$data) {
return ;
}
switch ($data['type']) {
case 'init':
Gateway::bindUid($client_id, $data['from_id']);
return;
case 'say':
$response = [
'data' => $data['data'],
'type' => $data['type']
];
Gateway::sendToUid($data['to_id'], json_encode($response));
return;
}
}
/**
* 当用户断开连接时触发
* @param int $client_id 连接id
*/
public static function onClose($client_id)
{
// 向所有人发送
GateWay::sendToAll("$client_id logout\r\n");
}
}
3.前端模板index.html文件
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="format-detection" content="telephone=no"/>
<title>沟通中</title>
<link rel="stylesheet" type="text/css" href="/static/newcj/css/themes.css?v=2017129">
<link rel="stylesheet" type="text/css" href="/static/newcj/css/h5app.css">
<link rel="stylesheet" type="text/css" href="/static/newcj/fonts/iconfont.css?v=2016070717">
<script src="/static/newcj/js/jquery.min.js"></script>
<script src="/static/newcj/js/dist/flexible/flexible_css.debug.js"></script>
<script src="/static/newcj/js/dist/flexible/flexible.debug.js"></script>
</head>
<body ontouchstart>
<div class='fui-page-group'>
<div class='fui-page chatDetail-page'>
<div class="chat-header flex">
<i class="icon icon-toleft t-48"></i>
<span class="shop-titlte t-30">商店</span>
<span class="shop-online t-26"></span>
<span class="into-shop">进店</span>
</div>
<div class="fui-content navbar" style="padding:1.2rem 0 1.35rem 0;">
<div class="chat-content">
<p style="display: none;text-align: center;padding-top: 0.5rem" id="more"><a>加载更多</a></p>
<p class="chat-time"><span class="time">2017-11-12</span></p>
</div>
</div>
<div class="fix-send flex footer-bar">
<i class="icon icon-emoji1 t-50"></i>
<input class="send-input t-28" maxlength="200">
<i class="icon icon-add t-50" style="color: #888;"></i>
<span class="send-btn">发送</span>
</div>
</div>
</div>
<script>
var ws = new WebSocket('ws://127.0.0.1:8282');
var from_id = {$from_id};
var to_id = {$to_id};
ws.onmessage = function (e) {
let response = eval('(' + e.data + ')');
switch (response.type) {
case 'init':
let data = '{"type": "init", "from_id": "'+from_id+'"}';
ws.send(data);
return;
case 'say':
$('.chat-content').append('<div class="chat-text section-left flex">\n' +
' <span class="char-img"\n' +
' style="background-image: url(http://chat.lo/static/newcj/img/123.jpg)"></span>\n' +
' <span class="text"><i class="icon icon-sanjiao4 t-32"></i>'+ response.data +'</span>\n' +
' </div>');
return;
}
}
$('.send-btn').click(function () {
let txt = $('.send-input').val();
let message = '{"data": "' + txt + '", "type": "say", "from_id": "'+from_id+'", "to_id":"'+to_id+'"}';
ws.send(message);
$('.chat-content').append('<div class="chat-text section-right flex">\n' +
' <span class="text"><i class="icon icon-sanjiao3 t-32"></i>'+txt+'</span>\n' +
' <span class="char-img"\n' +
' style="background-image: url(http://chat.lo/static/newcj/img/132.jpg)"></span>\n' +
' </div>');
$('.send-input').val("");
})
</script>
</body>
</html>