<?php
class Ws
{
protected $host = "0.0.0.0";
protected $port = 8812;
public $ws = null;
public function __construct()
{
$this->ws = new Swoole\WebSocket\Server($this->host, $this->port);
$this->ws->set(
[
'worker_num' => 2,
'task_worker_num' => 2,
]
);
$this->ws->on("open", [$this, 'onOpen']);
$this->ws->on("message", [$this, 'onMessage']);
$this->ws->on("task", [$this, 'onTask']);
$this->ws->on("finish", [$this, 'onFinish']);
$this->ws->on("close", [$this, 'onClose']);
$this->ws->start();
}
/**
* 监听ws连接事件
* @param $ws
* @param $request
*/
public function onOpen($ws, $request)
{
var_dump($request->fd);
var_dump($request);
/* if ($request->fd == 1) {
//每2秒执行
swoole_timer_tick(2000, function ($timer_id) {
echo "2s: timerId:{$timer_id}\n";
});
}*/
}
/**
* 监听ws消息事件
* @param $ws
* @param $frame
*/
public function onMessage($ws, $frame)
{
echo "ser-push-message:{$frame->data}\n";
$after_data = json_decode($frame->data, true);
//用户登录时链接该socket时,进行存储用户的$frame->fd
if (isset($after_data['user_id'])) {
(new iRedis())->setUserFd($after_data['user_id'], $frame->fd);
}
//执行给单个用户发送信息的逻辑
if (isset($after_data['uid'])) {
//根据获得的uid进行查询数据库得到该用户的$frame->fd,并判断用户是否在线,在线时进行发送信息
$user_status = (new iRedis())->getUserIdStatus($after_data['uid']);
if ($user_status) {
$user_fd = (new iRedis())->getUserFd($after_data['uid']);
$ws->push($user_fd, json_encode($frame->data));
}else{
//进行存储消息,待用户上线的时候发送消息
}
}
//echo $frame->fd . PHP_EOL;
// todo 10s
/*$data = [
'task' => 1,
'fd' => $frame->fd,
];
$ws->task($data);
/*
swoole_timer_after(5000, function () use ($ws, $frame) {
echo "5s-after\n";
$ws->push($frame->fd, "server-time-after:");
});*/
}
/**
* @param $serv
* @param $taskId
* @param $workerId
* @param $data
*/
public function onTask($serv, $taskId, $workerId, $data)
{
//print_r($data);
// 耗时场景 10s
//sleep(10);
return "on task finish"; // 告诉worker
}
/**
* @param $serv
* @param $taskId
* @param $data
*/
public function onFinish($serv, $taskId, $data)
{
echo "taskId:{$taskId}\n";
echo "finish-data-sucess:{$data}\n";
}
/**
* close
* @param $ws
* @param $fd
*/
public function onClose($ws, $fd)
{
echo "clientid:{$fd}\n";
}
}
class iRedis
{
protected $host = "127.0.0.1";
protected $port = 6379;
public $redis = null;
public function __construct()
{
$this->redis = new Redis();
$this->redis->connect($this->host, $this->port);
}
public function setUserFd($userId, $fd)
{
$this->redis->set($userId, $fd);
$this->redis->set($userId . '_status', 1);
}
public function getUserFd($userId)
{
return $this->redis->get($userId);
}
public function getUserIdStatus($userId)
{
return $this->redis->get($userId . '_status');
}
public function closeUserFd($userId)
{
return $this->redis->set($userId . '_status', 0);
}
}
$obj = new Ws();
js代码
<script>
var websocket = new WebSocket("ws://111.231.74.213:8812");
//实例对象的onopen属性
websocket.onopen = function (evt) {
console.log('首次链接的时候,发送改的uid')
websocket.send('{"user_id":1}');
}
// 实例化 onmessage
websocket.onmessage = function (evt) {
console.log("ws-server-return-data:" + evt.data);
}
//onclose
websocket.onclose = function (evt) {
console.log("close");
}
//onerror
websocket.onerror = function (evt, e) {
console.log("error:" + evt.data);
}
function sendmessage() {
//uid 发送给需要接收的用户
websocket.send('{"uid":"2","message":"' + document.getElementById('input').value + '"}');
}
</script>