这次使用的是laravel框架:
1、安装workerman/gateway-worker
终端项目目录下输入:
composer require workerman/gateway-worker
2、创建workerman启动文件
php artisan make:command Workerman
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use GatewayWorker\BusinessWorker;
use GatewayWorker\Gateway;
use GatewayWorker\Register;
use Workerman\Worker;
class Workerman extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'workerman {action} {--d}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Start a Workerman server.';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
//
global $argv;
$action = $this->argument('action');
$argv[0] = 'artisan workerman';
$argv[1] = $action;
$argv[2] = $this->option('d') ? '-d' : ''; //必须是一个-,上面定义命令两个--,后台启动用两个--
$this->start();
}
private function start()
{
$this->startGateWay();
$this->startBusinessWorker();
$this->startRegister();
Worker::runAll();
}
private function startBusinessWorker()
{
$worker = new BusinessWorker();
$worker->name = 'BusinessWorker';
$worker->count = 1;
$worker->registerAddress = '127.0.0.1:1236';
$worker->eventHandler = \App\GatewayWorker\Events::class;
}
private function startGateWay()
{
$gateway = new Gateway("websocket://0.0.0.0:2346");
$gateway->name = 'Gateway';
$gateway->count = 1;
$gateway->lanIp = '127.0.0.1';
$gateway->startPort = 2300;
$gateway->pingInterval = 30;
$gateway->pingNotResponseLimit = 0;
$gateway->pingData = '{"type":"ping"}';
$gateway->registerAddress = '127.0.0.1:1236';
}
private function startRegister()
{
new Register('text://0.0.0.0:1236');
}
}
3、创建事件监听文件
创建一个 app/GatewayWorker/Events.php 文件来监听处理 workman 的各种事件
<?php
namespace App\GatewayWorker;
use GatewayWorker\Lib\Gateway;
use Illuminate\Support\Facades\Log;
class Events
{
public static function onWorkerStart($businessWorker)
{
echo "onWorkerStart\r\n";
}
public static function onConnect($client_id)
{
Gateway::sendToClient($client_id, json_encode(['type' => 'onConnect', 'client_id' => $client_id]));
// echo $client_id;
echo $client_id."登陆成功\r\n";
}
public static function onWebSocketConnect($client_id, $data)
{
echo "onWebSocketConnect\r\n";
}
public static function onMessage($client_id, $message)
{
Gateway::sendToClient($client_id,$message);
echo $message;
// Gateway::sendToClient($client_id, json_encode(['type' => 'onMessage', 'client_id' => $client_id, 'name' => json_decode($message)->name]));
// echo "onMessage\r\n";
}
public static function onClose($client_id)
{
Log::info('Workerman close connection' . $client_id);
echo "onClose\r\n";
}
}
4、测试。启动workerman服务端
php artisan workerman start --d
在浏览器 F12 打开调试模式,在 Console 里输入
ws = new WebSocket("ws://ipaddress:2346");
ws.onopen = function() {
ws . send('{"name":"one","user_id":"111"}');
ws . send('{"name":"two","user_id":"222"}');
};
ws.onmessage = function(e) {
console.log("收到服务端的消息:" + e.data);
};
ws.onclose = function(e) {
console.log("服务已断开" );
}
console收到服务器端的消息.....
如在控制器里使用,需要
public function __construct()
{
// 设置GatewayWorker服务的Register服务ip和端口,请根据实际情况改成实际值(ip不能是0.0.0.0)
Gateway::$registerAddress = '127.0.0.1:1236';
}
doc2.workerman.net/
5、长链接使用代码
后端:
<?php
namespace App\Http\Controllers\chat;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Redis;
use App\GatewayWorker\Events;
use GatewayWorker\Lib\Gateway;
class Chat
{
public function __construct()
{
// 设置GatewayWorker服务的Register服务ip和端口,请根据实际情况改成实际值(ip不能是0.0.0.0)
Gateway::$registerAddress = '127.0.0.1:1236';
}
public function talks()
{
return view('chat.talks');
}
public function talk(Request $request)
{
return view('chat.talk');
}
public function loginConfirm(Request $request)
{
$name = $request->post('name');
if ($name) {
$user = Redis::sAdd('name',$name);
// if ($user) {
return response()->json(['code'=>200]);
// }
}
}
public function getList(Request $request)
{
$to = $request->get('name');
$list = Redis::sMembers('name');
foreach ($list as $k=>$v)
{
$unread = Redis::hGet('unread_'.$to, $v);
$list[$k] = array('name'=>$v, 'unread'=>$unread);
}
if ($list) {
return response()->json(['code'=>200, 'list'=>$list]);
}
}
public function content(Request $request)
{
$client_id = $request->post('client_id');
$content = $request->post('content');
$from = $request->post('from');
$to = $request->post('to');
$plus = strcmp(md5($from), md5($to));
if ($plus == 0) {
$res = $from.$to;
} else if ($plus < 0) {
$res = $from.$to;
} else if ($plus >0) {
$res = $to.$from;
}
$data = json_encode(array('from'=>$from, 'to'=>$to, 'message'=>$content, 'time'=>time()),JSON_UNESCAPED_UNICODE,true);
$keyName = 'mes:'.$res;
$insert = Redis::rPush($keyName, $data);
$unread = Redis::hIncrBy('unread_'.$to,$from,1);
if ($insert&&$unread) {
Gateway::sendToGroup($res,$data);
return response()->json(['code'=>200]);
}
}
public function mesList(Request $request)
{
$from = $request->get('from');
$to = $request->get('to');
$plus = strcmp(md5($from), md5($to));
if ($plus == 0) {
$res = $from.$to;
} else if ($plus < 0) {
$res = $from.$to;
} else if ($plus >0) {
$res = $to.$from;
}
$list = Redis::lrange('mes:'.$res,-10,-1);
foreach( $list as $k=>$v) {
$list[$k] = json_decode($v);
}
Redis::hSet('unread_'.$from, $to, 0);
$client_id = $request->get('client_id');
Gateway::joinGroup($client_id, $res);
return response()->json(['code'=>200, 'list'=>$list]);
}
public function mesRead(Request $request)
{
$from = $request->input('from');
$to = $request->input('to');
Redis::hSet('unread_'.$from, $to, 0);
}
}
前端:
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title></title>
<link rel="stylesheet" type="text/css" href="https://res.wx.qq.com/open/libs/weui/2.4.1/weui.min.css">
</head>
<body style="background-color: #ececec">
<div class="page">
<div style="width: 100%;background-color: #00AAAA" @click="back">《后退</div>
<div v-for="list in lists">
<div v-if="list.from==master" style="text-align: right">
<span style="background-color: yellowgreen;">@{{ list.message }}</span>
<span style="">@{{list.from}}</span>
</div>
<div v-else style="text-align: left">
<span style="">@{{list.from}}</span>
<span style="background-color: white;">@{{ list.message }}</span>
</div>
</div>
<div style="position: fixed;bottom: 0;">
<input type="text" v-model="content" style="height: 2rem" placeholder="填写聊天内容"/>
<a href="javascript:" class="weui-btn weui-btn_mini weui-btn_primary" style="line-height: initial;overflow: initial" @click="send">发送</a>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.12"></script>
<script src="https://unpkg.com/axios@0.21.1/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/js-cookie@2/src/js.cookie.min.js"></script>
<script type="text/javascript">
var Ca = new Vue({
el:".page",
data(){
return{
content: '',
lists: [],
master: '',
client_id: ''
}
},
created: function(){
this.master = Cookies.get('name');
ws = new WebSocket("ws://www.dzzzh.com:2346");
ws.onmessage = function(e) {
console.log(e)
let eJson = JSON.parse(e.data)
if (eJson.type == "onConnect") {
// Cookies.set('client_id', eJson.client_id)
Ca.client_id = eJson.client_id
Ca.mesList()
}
if (eJson.message){
Ca.lists.push(eJson)
Ca.read()
}
console.log("收到服务端的消息:" + e.data);
};
},
methods:{
back(){
window.location.href="{{url('/talks')}}"
},
send(){
axios.post("{{url('/api/content')}}",{
from: "{{$_GET['name']}}",
to: "{{$_GET['to']}}",
content: this.content,
client_id: this.client_id
}).then(function(res){
if (res.data.code === 200) {
Ca.content = '';
}
}).catch(function(err){
console.error(err)
})
},
mesList(){
axios.get("{{url('/api/mesList')}}",{params:{
from:"{{$_GET['name']}}",
to:"{{$_GET['to']}}",
client_id: Ca.client_id
}}).then(function(res){
if (res.data.code === 200) {
Ca.lists = res.data.list
}
}).catch(function(err){
console.error(err)
})
},
read(){
axios.put("{{url('/api/mesRead')}}",{params:{
from: "{{$_GET['name']}}",
to: "{{$_GET['to']}}",
}}).then(function(res){
console.log(res)
}).catch(function(err){
console.log(err)
})
}
}
})
</script>
</body>
</html>
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!