这里用得不是workerman框架而是gatewayworker手册。
因为做的是客户端与客户端之间的通讯。
php方面使用的是thinkphp框架。
现在开始重新讲一下怎么搞这个单对单聊天系统。
首先下载好thinkphp5与gatewayworker之后把gate(简读)放到thinkphp5的vendor文件夹下,
![](https://img.kancloud.cn/84/27/8427181565784f01e2d9f3ec5a718c03_179x360.png)
然后对gate框架的start_gateway.php文件进行配置
![](https://img.kancloud.cn/ca/ed/caed025763ba3d16c963133e186ab3f9_693x652.png)
业务逻辑代码主要放在Events.php文件里。
这是gate的目录结构:
![](https://img.kancloud.cn/31/3f/313fc8fecd064dab20fff07576a717ac_836x412.png)
然后就是前端代码了,我这里是用别人教程的一个模板,根据里面的代码做一下简单的修改,适合入门。
这里是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="https://code.jquery.com/jquery-3.0.0.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 fromid = 12;
//
var toid = 13;
var API_URL = "http://localhost/tchat/public/index.php/api/api/";
var ws = new WebSocket("ws://192.168.0.102:8282");
// var ws = new WebSocket("ws://192.168.10.51:8282");
ws.onmessage = function(e){
var message = eval("("+e.data+")");
switch (message.type){
case "init":
var bild = '{"type":"bind","fromid":"'+fromid+'"}';
ws.send(bild);
return;
case "text":
console.log(message);
if(toid==message.fromid) {
$(".chat-content").append(' <div class="chat-text section-left flex"><span class="char-img" style="background-image:"></span> <span class="text"><i class="icon icon-sanjiao4 t-32"></i>' + message.data + '</span> </div>');
} return;
case "save":
save_message(message);
return;
}
// $(".chat-content").append(' <div class="chat-text section-left flex"><span class="char-img" style="background-image: "></span> <span class="text"><i class="icon icon-sanjiao4 t-32"></i>' + message.data + '</span> </div>');
// console.log(message);
}
$(".send-btn").click(function(){
var text = $(".send-input").val();
var message = '{"data":"'+text+'","type":"say","fromid":"'+fromid+'","toid":"'+toid+'"}';
$(".chat-content").append('<div class="chat-text section-right flex"><span class="text"><i class="icon icon-sanjiao3 t-32"></i>'+text+'</span> <span class="char-img" style="background-image: "></span> </div>');
ws.send(message);
$(".send-input").val("");
})
function save_message(message){
$.post(
API_URL+"insertchat" ,
message,
function(){
},'json'
)
}
</script>
</body>
</html>
````
下面是php逻辑代码:
~~~
<?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)
{
//global是设置全局变量的函数
global $num;
// 向当前client_id发送数据
//Gateway::sendToClient($client_id, "Hello $client_id\r\n");
// 向所有人发送
// Gateway::sendToAll("$client_id login\r\n");
$data = json_encode(array('type'=>'init','client_id'=>$client_id));
echo "connect".++$num.":".$client_id."\n";
发送数据到指定clientid里
Gateway::sendToClient($client_id,$data);
}
/**
* 当客户端发来消息时触发
* @param int $client_id 连接id
* @param mixed $message 具体消息
*/
public static function onMessage($client_id, $message)
{
// 向所有人发送
$message_data = json_decode($message,true);
if(!$message_data){
return;
}
switch($message_data['type']){
case "bind":
$fromid = $message_data['fromid'];
//绑定clientid到用户id里,发送消息通过用户id发送
Gateway::bindUid($client_id, $fromid);
echo "datasend".$fromid."\n";
return;
case "say":
//解析字符串成html字符串
$text = nl2br(htmlspecialchars($message_data['data']));
$fromid = $message_data['fromid'];
$toid = $message_data['toid'];
$date=[
'type'=>'text',
'data'=>$text,
'fromid'=>$fromid,
'toid'=>$toid,
'time'=>time()
];
echo "datasend".$fromid."\n";
echo "datasend".$toid."\n";
//传输数据到指定用户id
Gateway::sendToUid($toid,json_encode($date));
return;
}
}
/**
* 当用户断开连接时触发
* @param int $client_id 连接id
*/
public static function onClose($client_id)
{
// 向所有人发送
echo "logout:".$client_id."\n";
}
}
~~~
功能到这里已经基本实现了,后面还会对消息进行数据库记录