1.我使用的是linux系统,首先需要安装think-swoole
composer require topthink/think-swoole
2.在项目根目录config目录下修改swoole_server.php,没有自己新建。
<?php
// +----------------------------------------------------------------------
// | Swoole设置 php think swoole:server 命令行下有效
// +----------------------------------------------------------------------
return [
'swoole_class' => 'app\index\controller\Swoole',
];
3.因为上面指向新的swoole.php ,所以我们去index模块新建Swoole.php.
?4.自己重写Swoole.php
<?php
namespace app\index\controller;
common下的是我自己的模型,因为下面用到了用不到的可以去掉
use app\common\model\ImFriend;
use app\common\model\ImMessage;
use app\common\model\User;
///模型结束
use think\swoole\Server;
use think\Db;
class Swoole extends Server
{
protected $host = ''; 你的域名
protected $port = 9500;
protected $type = 'socket';
protected $serverType = 'ssl';
protected $mode = SWOOLE_PROCESS;
protected $sockType = SWOOLE_SOCK_TCP | SWOOLE_SSL;
protected $option = [
'worker_num'=> 4,
'daemonize' => false,
'backlog' => 128,
'ssl_key_file' => '', ///key证书
'ssl_cert_file' => '',cert证书
'heartbeat_check_interval' => 10,
'heartbeat_idle_time' => 300,
'buffer_output_size' => 4*1024*1024, // 发送输出缓存区内存
'socket_buffer_size' => 4*1024*1024, // 配置客户端连接的缓存区长度
];
//心跳检测:每60秒遍历所有连接,强制关闭10分钟内没有向服务器发送任何数据的连接
// 事件回调定义
public function onOpen($server, $request) {
//将user_id 和fd 传到数据库 (后面将使用redis)
$date=date('Y-m-d H:i',time());
目前使用的是自增id,后面改成token
$user_id=$request->get['user_id'];
/*插入之前将所有的该userid状态改为0*/
Db::table('im_user_status')->where('user_id',$user_id)->update(['status'=>0,'update_time'=>$date]);
Db::table('im_user_status')->insert(['user_id'=>$user_id,'fd'=>$request->fd,'create_time'=>$date]);
$res['type']='success';//发送信息
$res['msg']='连接成功';//发送信息
$server->push($request->fd, json_encode($res));
echo "client {$request->fd} 打开\n";
}
public function onMessage($server, $frame) {
$data=json_decode($frame->data);
//内容
switch ($data->type) {
case 'check':
$res['type']='success';//发送信息
$res['msg']='检测成功';//检测是否连接
$server->push($frame->fd, json_encode($res));
break;
case 'user':
$this->send($server,$frame,$data); //发送点对点消息
break;
case 'system':
$this->systemsend($server,$frame,$data); //发送系统消息
break;
default:
$res['msg']='默认';
};
}
public function onRequest($request, $response) {
var_dump('onrequest'.$request);
$response->end("<h1>Hello Swoole. #" . rand(1000, 9999) . "</h1>");
}
public function onClose($ser, $fd) {
Db::table('im_user_status')->where('fd',$fd)->where('status',1)->update(['status'=>0]);
echo "client {$fd} closed为啥呢\n";
}
public function onReceive($server, $fd, $from_id, $data)
{
echo "name {$data}";
$server->send($fd, 'Swoole: '.$data);
}
//用户的信息发送
public function send($server,$frame,$data){
$type=$data->msg->type; //信息类型
$length=0; //录音长度
switch ($type) {
case 'text':
$name='text';
$content=$data->msg->content->text;
break;
case 'img':
$name='url';
$content=$data->msg->content->url;
break;
case 'voice':
$name='url';
$content=$data->msg->content->url;
$length=$data->msg->content->length;
break;
default:
$content=$data->msg->content->text;
};
//来源的id
$fromid=$data->fromid;
//要发送的id
$toid=$data->toid;
$username=$data->msg->userinfo->username;
$avatar=$data->msg->userinfo->face;
$date=date('Y-m-d H:i:s',time());
//var_dump($frame);
// var_dump($data);
// echo "receive from {$frame->fd}:{$frame->data},opcode:{$frame->opcode},fin:{$frame->finish}\n";
$a=ImFriend::where('user_id',$data->fromid)->where('friend_id',$data->toid)->find();
//表示不是好友自动加
if(empty($a)){
$a=ImFriend::create(['user_id',$data->fromid,'friend_id',$data->toid]);
}
//将信息插入表中
$id=ImMessage::create(['message_content'=>$content,'voice_length'=>$length,'type'=>$type,'from_user_id'=>$fromid,'from_user_name'=>$username,'from_user_avatar'=>$avatar,'to_user_id'=>$toid]);
//查找朋友的fd
$f=Db::table('im_user_status')->where('user_id',$toid)->where('status',1)->field('fd')->find();
echo $f['fd'];
if(!is_null($f)){
/*表示查到了意味着在线*/
$res['message']['sendmethod']='user';
$res['message']['type']='user';
$res['message']['fromid']=$fromid;
$res['message']['msg']['type']=$type;
$res['message']['msg']['content'][$name]=$content;
$res['message']['msg']['content']['length']=$length;
$res['message']['msg']['id']=$id->id;
$res['message']['msg']['time']=$date;
$res['message']['msg']['userinfo']['uid']=$fromid;
$res['message']['msg']['userinfo']['username']=$username;
$res['message']['msg']['userinfo']['face']=$avatar;
$res['type']='getmessage';//发送信息
$server->push($f['fd'], json_encode($res));
echo "发送信息成功";
}else {
/*如果不在线则需要进行下一步操作如缓存消息*/
}
return ;
}
public function systemsend($server,$frame,$data)
{
$type=$data->msg->type; //信息类型
$length=0; //录音长度
switch ($type) {
case 'text':
$name='text';
$content=$data->msg->content->text;
break;
case 'img':
$name='url';
$content=$data->msg->content->url;
break;
case 'voice':
$name='url';
$content=$data->msg->content->url;
$length=$data->msg->content->length;
break;
default:
$content=$data->msg->content->text;
};
//来源的id
$fromid=$data->fromid;
//要发送的id
$toid=$data->toid;
$username=$data->msg->userinfo->username;
$avatar=$data->msg->userinfo->face;
$date=date('Y-m-d H:i:s',time());
//将信息插入表中
$id=ImMessage::create(['message_content'=>$content,'voice_length'=>$length,'type'=>$type,'from_user_id'=>$fromid,'to_user_id'=>$toid]);
//根据id或者关键字查找答案
$ids=$data->msg->content->content_id;
$systemcontent=Db::table('im_system_content')->where('id',$ids)->find();
$res['message']['sendmethod']='system';
$res['message']['type']='system';
$res['message']['fromid']=$fromid;
$res['message']['toid']=$toid;
$res['message']['msg']['type']=$type;
$res['message']['msg']['content'][$name]=$systemcontent['content'];
$res['message']['msg']['id']=$id->id;
$res['message']['msg']['time']=$date;
$res['message']['msg']['userinfo']['uid']=$toid;
$res['type']='getmessage';//发送信息
$server->push($frame->fd, json_encode($res));
return ;
}
}
5.我们还需要一个测试端,我直接写在了php里,
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>websocket client</title>
</head>
<button type="button" id="send">发送</button>
<body>
<h1>swoole-ws测试</h1>
<script>
var wsUrl = 'wss://aaa.xw.com:9500';
var websocket = new WebSocket(wsUrl);
websocket.onopen = function (evt) {
console.log("ws client 连接成功!");
};
document.getElementById('send').onclick = function () {
websocket.send('{"url":"index/index/websocket"}');
console.log('ws client 发送数据');
};
websocket.onmessage = function (evt) {
console.log("server return data: " + evt.data);
};
websocket.onclose = function (evt) {
console.log("connect close");
};
websocket.onerror = function (evt, e) {
console.log("error: " +JSON.stringify(evt));
}
</script>
</body>
</html>
6.启动php服务 使用命令?
php think swoole:server
?
7.测试是否链接成功
?
|