这次写的不依赖框架,不用nginx配置,只是依靠swoole的http_server和websocket,也是用的多端口监听,一边实现了web端的访问,一边实现了socket的发送;
文档在这里,可以多认真的读一下:https://wiki.swoole.com/wiki/page/525.html
好的,直接上码;
http.php
<?php namespace app\common; require_once 'Predis.php'; require_once 'Task.php'; /** * socket面向对象的编译 */ class Http { CONST HOST='0.0.0.0'; CONST PORT='9501'; public $ws=null; public $http_server=null; public function __construct() { $this->ws=new \swoole_websocket_server(self::HOST,self::PORT); $this->ws->set([ //心跳检测 // 'heartbeat_check_interval' => 5, // 'heartbeat_idle_time' => 10, ]); //监听新端口 $this->http_server=$this->ws->listen("0.0.0.0", 9502, SWOOLE_SOCK_TCP); //开启http模式 $this->http_server->set([ 'open_http_protocol' => true, ]); $this->ws->on("start", [$this, 'onStart']); $this->http_server->on("request", [$this, 'onRequest']); $this->ws->on('message',[$this,'onmessage']); $this->ws->on('close',[$this,'onclose']); $this->http_server->on('close',[$this,'oncloses']); $this->ws->start(); } //监听数据接收事件 public function onRequest($request, $response) { //获取全部的参数 $data=$request->get; //判断类型 if ($data['type'] == 'start') { //开始拍卖 //组装数据 $arr['number']=count(Predis::getInstance()->hgetall($data['room_id']))-1; $arr['type']="start"; self::push_room($data['room_id'],$arr); $response->end(json_encode(['code'=>200,'message'=>"推送成功",'data'=>null])); }elseif ($data['type'] == 'change') { //出价成功 //组装数据 $arr['name']=$data['name']; $arr['price']=$data['price']; $arr['type']="change"; self::push_room($data['room_id'],$arr); $response->end(json_encode(['code'=>200,'message'=>"推送成功",'data'=>null])); }elseif ($data['type'] == 'end') { //拍卖结束 $arr['name']=$data['name']; $arr['price']=$data['price']; $arr['type']="end"; self::push_room($data['room_id'],$arr); //删除对应的房间 Predis::getInstance()->del($data['room_id']); Predis::getInstance()->srem('group',$data['room_id']); $response->end(json_encode(['code'=>200,'message'=>"推送成功",'data'=>null])); } } /** * $room_id 当前房间id * $arr 组装数据 */ public function push_room($room_id,$arr) { //获取在线用户的fd $push_arr=Predis::getInstance()->hvals($room_id); //推送 foreach ($push_arr as $v) { $this->ws->push($v, json_encode($arr)); } } /** * 设置进程名,为后续平滑重启进程 * @param $server */ public function onStart($server) { swoole_set_process_name("live_master"); } /** 监听接收事件的回调 */ public function onmessage($server, $frame) { //在接收数据的时候进行推送 $data=json_decode($frame->data,true); //加入分组 Predis::getInstance()->hset($data['room_id'],$data['uid'],$frame->fd); //加入组集合 Predis::getInstance()->sadd('group',$data['room_id']); //组装数据 $arr['name']=$data['name']; $arr['type']="join"; $arr['number']=count(Predis::getInstance()->hgetall($data['room_id'])); //推送 self::push_room($data['room_id'],$arr); } /** 监听关闭事件的回调 */ public function onclose($ser, $fd) { print_r("你好,我的{$fd}\n"); //退出并删除多余的分组fd $group=Predis::getInstance()->sMembers('group'); foreach ($group as $v) { $fangjian=Predis::getInstance()->hgetall($v); foreach ($fangjian as $k => $vv) { if ($fd == $vv) { Predis::getInstance()->hdel($v,$k); } } } } public function oncloses($ser, $fd) { print_r("这个是http_server{$fd}\n"); } } new Http();
用户打开页面后我直接用socket的Onpen事件,所以这里就不用再写用户加入的判断逻辑了
index.html
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>我是来测试的</title> </head> <body> <h1>0</h1> <script type="text/javascript"> //连接服务 var wsServer = 'wss://code.77wx.cn:9503'; //实例化 var websocket = new WebSocket(wsServer); //监听开启事件(只负责监听,没有实际的开启作用) websocket.onopen = function (evt) { var data={ room_id:1, uid:'a', name:'夜袭寡妇村', }; websocket.send(JSON.stringify(data)); }; function log(msg){ console.log(msg); } //消息 websocket.onmessage = function (evt) { //监听消息后,直接给服务器传递消息 var e = JSON.parse(evt.data); switch(e.type){ //进入房间 case "join": log("用户进入房间,当前人数:"+e.num); alert("用户 "+e.name+" 进入房间,当前人数:"+e.number); break; //开始拍卖 case "start": log('拍卖开始,当前有'+e.number+'人和您同时竞拍!'); alert('拍卖开始,当前有'+e.number+'人和您同时竞拍!'); break; //用户出价 case "change": log("用户"+e.name+"出价:"+e.price+"元"); alert("用户 "+e.name+" 出价:"+e.price+"元"); break; //活动结束 case "end": alert("用户 "+e.name+" 以:"+e.price+"元,获得竞拍大奖"); log("用户 "+e.name+" 以:"+e.price+"元,获得竞拍大奖"); break; } console.log('来自server的最新消息: ' + evt.data); }; //关闭事件 websocket.onclose = function (evt) { console.log("我关闭了html"); }; //报错 websocket.onerror = function (evt, e) { console.log('Error occured: ' + evt.data); }; </script> </body> </html>