这次使用的是laravel框架:
1、安装workerman/gateway-worker
终端项目目录下输入:
composer require workerman/gateway-worker
2、创建workerman启动文件
php artisan make:command Workerman
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 的各种事件
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';
}
复制代码
5、长链接使用代码
后端:
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);
}
}
复制代码
前端:
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
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)
})
}
}
})
复制代码