本文系麥子時光原創,轉載請注明出處,謝謝
http://www.lxweimin.com/p/ff6ec1e143cb
不要用下面方法?
看下 thinkphp 的入口文件? index.php?
自動加載過程 非常的 溜 。。。。
我們自己建立一個 專門為 swoole 啟動用的
入口文件 為了體現 這個文件放置的隨意性 我們把
它建在 和 app 平級的目錄中 ,且叫叫 tasktest.php
從index.php 拷貝配置??
define('APP_PATH', __DIR__ . '/app/');
// 下面? 這個最 主要的配置? 就是 綁定 模塊到 指定 swoole 啟動的? 文件? 名字隨意? 對應就好
define('BIND_MODULE','core/Sio');??
define('ROOT_PATH', __DIR__ . '/');
// 加載框架引導文件
require __DIR__ . '/thinkphp/start.php';
這里我們 看下 對應的綁定模塊 core /sio
// 下面是我自己的業務 代碼?
其他三個函數
由于動用了task?
不要忘了finish
當然 還要用到clonse
現在 只要 運行?
本文系麥子時光原創,轉載請注明出處,謝謝
http://www.lxweimin.com/p/ff6ec1e143cb
app\core\controller\sio
部分 源碼分享
<?php
namespace app\core\controller;
use Swoole\Server;
use think\Controller;
use think\Db;
class Sio? extends Controller
{
protected $port = 9052;
? ? private $serv;
? ? private $db_config = [];
? ? private $redis_server = "127.0.0.1";
? ? private $redis_port = "6379";
? ? private $redis_pwd = "";
? ? private $all_fd_token_map = "all_tunnel_online_map";
? ? public function __construct()
{
/* 讀取站點配置 */
? ? ? ? $this->set_config();
? ? ? ? echo "構造函數初始化。。。\n";
//? ? ? ? var_dump(config("database"));
? ? ? ? $this->db_config= config("database");
? ? ? ? //redie 配置
? ? ? ? $this->redis_server= !empty(config("PUBLIC_REDIS_ADDR"))? config("PUBLIC_REDIS_ADDR"): "127.0.0.1";
? ? ? ? $this->redis_port= !empty(config("PUBLIC_REDIS_PORT"))? config("PUBLIC_REDIS_PORT"): "6379";
? ? ? ? $this->redis_pwd= !empty(config("PUBLIC_REDIS_PWD"))? config("PUBLIC_REDIS_PWD"): "";
? ? ? ? $this->clean_all_tunnel_key();
? ? ? ? //swoole
? ? ? ? $this->serv= new \swoole_server("0.0.0.0", $this->port);
? ? ? ? $this->serv->set(array(
'worker_num' => 8,//建議開啟的worker進程數為cpu核數的1-4倍
? ? ? ? ? ? 'daemonize' => false,
? ? ? ? ? ? 'max_request' => 10000,
? ? ? ? ? ? 'dispatch_mode' => 2,
? ? ? ? ? ? 'debug_mode' => 1,
? ? ? ? ? ? 'task_worker_num' => 8
? ? ? ? ));
//'reactor_num' => 8 //,默認會啟用CPU核數相同的數量, 一般設置為CPU核數的1-4倍,最大不得超過CPU核數*4。
? ? ? ? $this->serv->on('Start', array($this, 'onStart'));
? ? ? ? $this->serv->on('Connect', array($this, 'onConnect'));
? ? ? ? $this->serv->on('Receive', array($this, 'onReceive'));
? ? ? ? $this->serv->on('Close', array($this, 'onClose'));
? ? ? ? $this->serv->on('Task', array($this, 'onTask'));
? ? ? ? // bind callback
? ? ? ? $this->serv->on('Finish', array($this, 'onFinish'));
? ? ? ? $this->serv->start();
? ? ? ? if (!defined('GLOBAL_START')) {
$server = new Server();
? ? ? ? ? ? define('GLOBAL_START', true);
? ? ? ? }
}
public function onStart($serv)
{
echo "Start OK\n";
? ? ? ? echo "確保 onstart 時 所有的 相關都初始化 !重啟后 fd 會重頭再記錄 ,redis 里面的數據 將失準";
? ? ? ? dump(config("PUBLIC_REDIS_ADDR"));
? ? ? ? // 清空已有 的redis 相關業務 可能涵蓋 多平臺
? ? }
public function onConnect($serv, $fd, $from_id)
{
//? ? ? ? $serv->send($fd, "Hello {$fd}!");? // 打招呼
? ? ? ? echo "lingking——fd:----" . $fd;? ? ? // 打印
? ? ? ? echo " ";
? ? ? ? echo "lingking——from_id:----" . $from_id; // 打印work id
? ? }
public function onReceive(\swoole_server$serv, $fd, $from_id, $data)
{
echo "有新消息 來自客戶端 {$fd} Client :{$data}\n";
? ? ? ? if ($this->is_json($data)) {
$data = json_decode($data, true);
? ? ? ? }
$param = array(
'fd' => $fd,
? ? ? ? ? ? 'data' => $data
? ? ? ? );
? ? ? ? // start a task
? ? ? ? $serv->task(json_encode($param));
//? ? ? ? echo "上面已經 交個task? 這里不影響 做其他事 over\n";
? ? }
public function onTask($serv, $task_id, $from_id, $in_data)
{
$backbool = "false";
? ? ? ? //? ? ? ? echo "This Task {$task_id} from Worker {$from_id}\n";
//? ? ? ? echo "Data: {$in_data}\n";
//? ? ? ? var_dump(json_decode($in_data,true));
? ? ? ? $fd = json_decode($in_data, true)['fd'];
? ? ? ? $data = json_decode($in_data, true)['data'];
? ? ? ? if (!isset($data["token"])|| !isset($data["platform"])) {
echo "缺少token或者platform";
? ? ? ? ? ? $serv->send($fd, "缺少token或者platform");? // 這里作為回復客戶端
? ? ? ? ? ? return "fd: {$fd} Task {$task_id}'s result";
? ? ? ? }
//? data 中 有三參數 token platfom? info(內涵 now_mac? set mac)
? ? ? ? dump($this->redis_server);
? ? ? ? $redis = new \Redis();
? ? ? ? $redis->pconnect($this->redis_server, $this->redis_port);
? ? ? ? if (!empty($this->redis_pwd)) {
$redis->auth($this->redis_pwd);
? ? ? ? }
$tokenall = $data["token"];
? ? ? ? $time_length = 3 * 60;
? ? ? ? $bad_token_key = "aur_bad_token_" . $tokenall;
? ? ? ? $check_bool = $this->bad_token_check($bad_token_key);
? ? ? ? if (empty($check_bool)) {
$backbool = "false";
? ? ? ? ? ? $re_mag = $this->send_msg($fd, $backbool);? // 這里作為回復客戶端
? ? ? ? ? ? return "fd: {$fd} 觸發的 Task {$task_id} 的 結果:{$re_mag}\n";
? ? ? ? }
$platform = $data["platform"];
? ? ? ? $token = substr($tokenall, 0, 32);
? ? ? ? $tunnel_id = substr($tokenall, 33);
? ? ? ? //? 一個鍵 兩個囊? 一個放最大數量? 另一個放 fd 對? 用hash? token_all:[fd1:1,fd2:1....max_num:100]
? ? ? ? if ($platform == 4) {// 目前只有極光做了 隧道
? ? ? ? ? ? $out_key = "aur_tunnel_online_" . $tokenall;
? ? ? ? ? ? // 先驗證
? ? ? ? ? ? $have_fd = $redis->hExists($out_key, $fd);
? ? ? ? ? ? if ($have_fd) {
$backbool = "true";
? ? ? ? ? ? ? ? echo "有記錄 {$fd}\n";
? ? ? ? ? ? ? ? $re_mag = $this->send_msg($fd, $backbool);? // 這里作為回復客戶端
? ? ? ? ? ? ? ? return "fd: {$fd} 觸發的 Task {$task_id} 的 結果:{$re_mag}\n";
? ? ? ? ? ? }
echo "該id 沒有記錄 {$fd}\n";
? ? ? ? ? ? //? 沒有在里面 就 要重新搞了
? ? ? ? ? ? $have_max = $redis->hExists($out_key, "max_num");
? ? ? ? ? ? if (!$have_max) {
echo "沒找到最大數 {$out_key}\n";
? ? ? ? ? ? ? ? $tunnel_info = $this->set_max_num($prefix = "aur_", $tunnel_id, $token, $out_key);// 重置下
? ? ? ? ? ? ? ? if (!empty($tunnel_info)) {
$max_num = $tunnel_info["online_max_num"];
? ? ? ? ? ? ? ? ? ? $redis->hSet($out_key, "max_num", $max_num);
? ? ? ? ? ? ? ? ? ? echo "設置后獲取max_num:" . $redis->hGet($out_key, "max_num");
//? ? ? ? ? ? ? ? ? ? $redis->expire($out_key,5*60);// 60s? 從庫里面校驗
? ? ? ? ? ? ? ? }else {// 這里 要 做下阻擋 由于 非法token 一直查詢不到 ,每次過來查庫 對 數據庫造成壓力
//bad_token 入庫
? ? ? ? ? ? ? ? ? ? $redis->set("aur_bad_token_" . $tokenall, NOW_TIME + $time_length);
? ? ? ? ? ? ? ? ? ? $max_num = 0; //這里很重要? 就是 當 token 不對 時? $max_num
? ? ? ? ? ? ? ? }
}else {
$max_num = $redis->hGet($out_key, "max_num");
? ? ? ? ? ? }
$num_now = $redis->hLen($out_key)- 1;// 里面多了一個 鍵max_num
? ? ? ? ? ? echo " {$out_key}最大數:{$max_num},現在數:$num_now\n";
? ? ? ? ? ? if (!empty($max_num)&& $max_num > $num_now) {
// 驗證一個 并且放入 (有就算了)
? ? ? ? ? ? ? ? $new_fd = $redis->hSet($out_key, $fd, $fd);
? ? ? ? ? ? ? ? $map_up = $redis->hSet($this->all_fd_token_map, $fd, $out_key); //? all_tunnel_online_map:[fd1:aurtoken,fd2:inttoken2,fd3:token2]
? ? ? ? ? ? ? ? echo "new_fd {$fd} 入庫 \n";
? ? ? ? ? ? ? ? echo "{$fd}:{$out_key}map 入庫結果:{$map_up}\n";
? ? ? ? ? ? ? ? var_dump($new_fd);
? ? ? ? ? ? ? ? $backbool = "true";
? ? ? ? ? ? }
}else {// 如果有其他的 請在這里 做分支判斷
? ? ? ? }
$redis->close();
? ? ? ? $msg = $this->send_msg($fd, $backbool);? // 這里作為回復客戶端
? ? ? ? return "fd: {$fd} Task {$task_id}'s 結果{$msg}";
? ? }
private function bad_token_check($bad_token_key)
{
$redis = new \Redis();
? ? ? ? $redis->pconnect($this->redis_server, $this->redis_port);
? ? ? ? if (!empty($this->redis_pwd)) {
$redis->auth($this->redis_pwd);
? ? ? ? }
$expire = $redis->get($bad_token_key);
? ? ? ? echo "bad 過期時間是:{$expire}\n";
? ? ? ? if ($expire > NOW_TIME) {//被鎖了
? ? ? ? ? ? echo "{$bad_token_key}這token是個壞小子\n";
? ? ? ? ? ? return false;
? ? ? ? }
return true;
? ? }
/**
* @param string $prefix
* @param $tunnel_id
* @param $token
* @param $out_key
* @return bool|mixed
*/
? ? private function set_max_num($prefix = "aur_", $tunnel_id, $token, $out_key)
{
// 矯正用
? ? ? ? echo "矯正ing....................................數據庫查詢\n";
? ? ? ? $tunnel_info = Db::connect($this->db_config)->table($prefix . "tunnel_user_package")->where(['id' => $tunnel_id])->find();
? ? ? ? if (!$tunnel_info) {
return false;
? ? ? ? }
if (md6($tunnel_id . "lingjiang735" . $tunnel_info["salt"])!= $token) {
return false;
? ? ? ? }
return $tunnel_info;
? ? }
public function send_msg($fd, $msg)
{
$reminder = "向->{$fd} 發送-> {$msg}\n";
? ? ? ? $this->serv->send($fd, $msg);
? ? ? ? return $reminder;
? ? }
public function onFinish($serv, $task_id, $data)
{
echo "Task {$task_id} over\n";
? ? ? ? echo "Finish: {$data}\n";
? ? }
public function onClose($serv, $fd, $from_id)
{
echo "1 Client {$fd} close connection\n";
? ? ? ? //? 這個端的唯一 鏈接 id
? ? ? ? $redis = new \Redis();
? ? ? ? $redis->pconnect($this->redis_server, $this->redis_port);
? ? ? ? if (!empty($this->redis_pwd)) {
$redis->auth($this->redis_pwd);
? ? ? ? }
$have_map = $redis->hExists($this->all_fd_token_map, $fd);
? ? ? ? echo "2 {$fd}是否有map?:\n";
? ? ? ? if ($have_map) {
$token_key = $redis->hGet($this->all_fd_token_map, $fd);
? ? ? ? ? ? echo "3 {$fd}查詢到token_key:{$token_key}\n";
? ? ? ? ? ? //刪除該token_key 下的
? ? ? ? ? ? $re = $redis->hDel($token_key, $fd);
? ? ? ? ? ? echo "4 {$fd}刪除結果:$re\n";
? ? ? ? ? ? echo "over\n";
? ? ? ? }else {
echo "3 {$fd}沒有查詢到token_key\n";
? ? ? ? }
$redis->close();
? ? }
private function is_json($str)
{
return is_array(json_decode($str, true))&& !empty(json_decode($str));
? ? }
/**
* 從數據庫拿到
*/
? ? private function set_config()
{
$m = Db::connect($this->db_config)->table('wt_config');
? ? ? ? $r = $m->select();
? ? ? ? foreach ($r as $k => $v) {
$r[$k]['name']= strtoupper($r[$k]['code']);
? ? ? ? }
$r = array_column($r, 'value', 'code');
? ? ? ? cache('config_cache', $r);
? ? ? ? //取配置,賦值
? ? ? ? config(cache('config_cache')); //添加配置
? ? ? ? echo "設置緩存";
? ? }
private function clean_all_tunnel_key()
{
$redis = new \Redis();
? ? ? ? $redisserver = $this->redis_server;
? ? ? ? $redisport = $this->redis_port;
? ? ? ? $redispwd = $this->redis_pwd;
? ? ? ? $redis->pconnect($redisserver, $redisport);
? ? ? ? if (!empty($redispwd)) {
$redis->auth($redispwd);
? ? ? ? }
echo "清理前各個token_list :\n";
? ? ? ? $infos = $redis->keys('aur_tunnel_online_*');
? ? ? ? dump($infos);
? ? ? ? $redis->delete($infos);
? ? ? ? echo "清理前各個token_list :\n";
? ? ? ? $infos = $redis->keys('aur_tunnel_online_*');
? ? ? ? dump($infos);
? ? ? ? echo "清理前map:\n";
? ? ? ? $infos = $redis->keys($this->all_fd_token_map);
? ? ? ? dump($infos);
? ? ? ? $redis->delete($infos);
? ? ? ? echo "清理前各個token_list and map:\n";
? ? ? ? $infos = $redis->keys($this->all_fd_token_map);
? ? ? ? dump($infos);
? ? }
}