服务端代码
<?php
//websocket服务器
//问题:
//1.消息发送,收件方可以有多人
//2.没有在线的发送不了,上线后发送
//3.发送失败,返回信息
//1.设置名称和得到当前没有接收的信息:'{"name":"index","operation":"setget"}';
//2.发送信息,to为数组'{"from":"index","to":{"0":"shijie","1":"ninini"},"info":"xxxxxxxx","operation":"sendinfo"}';
//基本思路:当连接完成时后,客户端发送数据,将自己链接重新命名,并查看redis中是否有自己未接收的信息,如果有就返回,每个链接重新命名后都是唯一的,当发送信息时,查看是否有当前客户端是否有链接,如果有链接就发送过去,并将status值改为ok,没有发送则为no,将二维数组存入redis中
use Workerman\Worker;
require_once './Workerman/Autoloader.php';
$websocket=new Worker('websocket://0.0.0.0:9501');
$redis=new Redis();
$redis->connect('x.x.x.x');
$redis->auth('sincityall');
$websocket->onWorkerStart=function($worker){
$i=0;
if($i<1){
echo "websocket服务已经启动\n" ;
}
++$i;
};
$websocket->onConnect=function($connection){
echo "有客户端已经连接\n";
};
$websocket->onMessage=function($connection,$data)use($redis,$websocket)
{
$data=json_decode($data,true);
//3.接收消息,转发消息 到达数据格式'{"from":"index","to":{"0":"shijie","1":"ninini"},"info":"xxxxxxxx","operation":"sendinfo"}';
if($data['operation']==='sendinfo')
{
sendinfo($connection,$data,$redis,$websocket);
}
//4.设置链接客户端唯一名称并返回多个数据 格式'{"name":"index","operation":"setget"}';
if($data['operation']==='setget')
{
setget($data,$redis,$connection);
}
};
//抗命名干扰
function setget($data,$redis,$connection)
{
$connection->id=$data['name'];
$infos=$redis->get($data['name']);
if($infos!==false)
{
$counts=0;
$returninfo=[];
$info=json_decode($infos,true);
foreach($info as $key=>$value)
{
if($value['status']==='no')
{
$returninfo[]=$value;
++$counts;
}
$info[$key]['status']='ok';
}
$return=json_encode(['status'=>200,'info'=>['counts'=>$counts,'info'=>$returninfo]]);
$connection->send($return);
$redis->set($data['name'],json_encode($info));
}else{
$return=json_encode(['status'=>202,'error'=>'当前没有信息','counts'=>0]);
$connection->send($return);
}
return false;
}
function sendinfo($connection,$data,$redis,$websocket)
{
//临时存储容器
$res['from']=$data['from'];
$res['info']=$data['info'];
foreach($data['to'] as $name)
{
$res['status']='no';
$res['to']=$name;
$res['time']=time();
foreach($websocket->connections as $conn)
{
if($conn->id===$name)
{
$returns=json_encode(['status'=>200,'info'=>$res]);
$conn->send($returns);
$res['status']='ok';
}
}
$infos=$redis->get($name);
if($infos!==false)
{
$info=json_decode($infos,true);
}else{
$info=[];
}
//查看是否redis是否有原来发送的数据,有数据将新数据加入后再存入redis中
$info[]=$res;
$redis->set($name,json_encode($info));
}
return false;
}
$websocket->onClose=function($connection){
echo "有客户端连接断开\n";
};
$websocket->onWorkerStop=function($connection){
echo "Workerman已经停止\n";
};
Worker::runAll();
客户端代码
<script>
var wsServer = 'ws://x.x.x.x:9501';
var websocket = new WebSocket(wsServer);
websocket.onopen = function (evt) {
console.log("正在链接...");
var info='{"name":"index","operation":"setget"}';
websocket.send(info);
var info='{"from":"index","to":{"0":"shijie","1":"ninini"},"info":"xxxxxxxx","operation":"sendinfo"}';
websocket.send(info);
};
websocket.onclose = function (evt) {
console.log("关闭链接...");
};
websocket.onmessage = function (evt) {
var data=eval('('+evt.data+')');
console.log(data);
};
websocket.onerror = function (evt, e) {
console.log('Error occured: ' + evt.data);
};
</script>