1、WebSoketServer是在swoole_http_server基础上增加了协议解析
2、完整的webSoket协议请求会被解析并封装在frame对象内
3、新增push方法用于发送websoket数据
回调函数
onHandShake
onHandShake WebSocket建立连接后进行握手。
WebSocket服务器已经内置了handshake,如果用户希望自己进行握手处理,可以设置onHandShake事件回调函数。
function onHandShake(swoole_http_request $request, swoole_http_response $response);
onHandShake事件回调是可选的 设置onHandShake回调函数后不会再触发onOpen事件,需要应用代码自行处理 onHandShake函数必须返回true表示握手成功,返回其他值表示握手失败
内置的握手协议为Sec-WebSocket-Version: 13,
低版本浏览器需要自行实现握手 1.8.1或更高版本可以使用server->defer调用onOpen逻辑
onOpen
当打开连接时候触发,在触发open事件的时候。可以通过连接的URL来判定用户。防止多联。
前端js代码
// ws = new WebSocket("wss://wss.wkcto.com/websocket");
ws = new WebSocket("ws://web.socket.com/websocket/1");
ws.onopen = function () {
//发送登录信息
var data = '{"type":"login","name":"' + "asd" + '"}';
ws.send(data);
};
ws.onmessage = onmessage;
php代码
public function onOpen($server, $request)
{
var_dump($request);
}
或者cookie来识别用户谁是谁?在onMessage之前进行判定
onMessage
注意:因为websocketServer是继承httpServer而来的所以也可以用onRequest回调的、那么如何判断连接是否为WebSocket客户端?
通过使用$server->connection_info($fd)获取连接信息,返回的数组中有一项为 websocket_status,根据此状态可以判断是否为WebSocket客户端
打印
完整的后端的代码
<?php
define('DS',DIRECTORY_SEPARATOR);
class webSocket{
private $serv;
private $reids;
public function __construct($ip="0.0.0.0",$port=1990)
{
$this->serv= new swoole_websocket_server($ip, $port);
$this->serv->set(array(
'worker_num' =>2,
// 'task_worker_num'=>2,
'daemonize' => false,
'max_request' => 10000,
'dispatch_mode' => 2,
));
$this->redis=new redis();
$this->redis->connect("127.0.0.1",6378);
$this->serv->on('workerStart',[$this,'onWorkerStart']);
$this->serv->on('open',[$this,'onOpen']);
$this->serv->on('message',[$this,'onMessage']);
$this->serv->on("close",[$this,"onClose"]);
$this->serv->start();
}
public function getFileData()
{
$day=date('d');
$fileName="online_".$day.".txt";
$file=__DIR__.DS.$fileName;
if(!is_file($file)){
file_put_contents($file,0);
return 0;
}else{
return file_get_contents($file);
}
}
public function setFileData(int $num)
{
$day=date('d');
$fileName="online_".$day.".txt";
$file=__DIR__.DS.$fileName;
file_put_contents($file,$num);
}
public function onWorkerStart($server, $workerId)
{
if($workerId==0){
//redis订阅连接了websocket可以利用前端发送广播
$client = new swoole_redis;
$client->on('message', function (swoole_redis $client, $result) use ($server) {
if ($result[0] == 'message') {
foreach($server->connections as $fd) {
$msg=['type'=>"push",'msg'=>$result[2],'fromUser'=>"系统",'toUser'=>0];
$server->push($fd, json_encode($msg));
}
}
});
$client->connect('127.0.0.1', 6379, function (swoole_redis $redis_client, $result) {
$redis_client->subscribe('test');
});
swoole_timer_tick(1000,function ($timer_id)use($server){
$onlineNum=$this->getFileData();
$connectionsNum=count($server->connections);
if($connectionsNum>$onlineNum){
$this->setFileData($connectionsNum);
}
});
}
}
public function onOpen($server, $request)
{
var_dump($request);
}
public function onMessage(swoole_websocket_server $server, $frame)
{
$requestMsg=json_decode($frame->data,true);
if(!is_array($requestMsg)){
$server->disconnect($frame->fd);
}
if($requestMsg['type']=="admin"){
$this->sendOnlineNum($server,$frame->fd);
}
if($requestMsg['type']=="login"){
$this->sendOnline($server,$frame->fd);
}
$msg=['type'=>"online",'msg'=>['bestOnline'=>0,'online'=>0,'date'=>date('Y-m-d H:i:s')],'msgType'=>1];
$msg=json_encode($msg);
$server->push($frame->fd, json_encode([]));
}
public function sendOnlineNum($server,$fd)
{
swoole_timer_tick(1000,function ($timer_id)use($server,$fd){
$best=$this->getFileData();
$msg=['type'=>"online",'msg'=>['bestOnline'=>$best,'online'=>count($server->connections),"date"=>date('Y-m-d H:i:s')],'msgType'=>1];
$msg=json_encode($msg);
try{
$bool=@$server->push($fd, $msg);
if($bool==false){
swoole_timer_clear($timer_id);
}
}catch (Exception $e){
}
});
}
public function onClose($server, $fd)
{
}
public function sendOnline($server, $fd)
{
var_dump($fd);
$this->redis->hSet("online",$fd,'1');
$msg=['type'=>"online",'msg'=>['bestOnline'=>10,'online'=>count($server->connections),"date"=>date('Y-m-d H:i:s')],'msgType'=>1];
$msg=json_encode($msg);
$bool=@$server->push($fd, $msg);
}
}
new webSocket();