Commit b9be0710 authored by 734642908@qq.com's avatar 734642908@qq.com

init

parent 8e9e35f8
# swooleframe
swoole框架websocket
project 应用部署目录
├─application 应用目录(可设置)
│ ├─socket 模块目录(可更改)
│ │ ├─controller 控制器目录
│ │ ├─model 模型目录
│ ├─common.php 应用公共(函数)文件
│ ├─config.php 应用(公共)配置文件
├─extend 扩展类库目录(可定义)
├─server.php 服务启动文件
├─swoole.log 运行log文件
├─README.md README 文件
请求协议:{"a":"login","m":"user","d":{"uid":"936258"}}
m:模块名称 a:操作方法 d:请求数据
返回格式:{"c":1,"msg":"获取成功","d":{"list":[]}}
c:状态码 msg:状态描述 d:数据内容
<?php
// 应用公共文件
function __autoload($class){
if(file_exists($GLOBALS['config']['socket_controller'].$class.'.php')) {
require_once($GLOBALS['config']['socket_controller'].$class.'.php');
}else{
echo_log("找不到对应的文件: $class ".__LINE__);
}
}
function echo_log($data,$data2=''){
//如果打开了调试
if(is_array($data) || is_object($data)) {
var_dump(date("Y-m-d H:i ") . $data);
} else {
echo(date("Y-m-d H:i ") . $data);
}
echo("\r\n");
if (!empty($data2)) {
if(is_array($data2) || is_object($data2)) {
var_dump(date("Y-m-d H:i ") . $data2);
} else {
echo($data2);
}
}
echo("\r\n\r\n");
}
function post_curl($url,$data,$header = array(), $is_ssl = false) {
$ch = curl_init(); // 启动一个CURL会话
curl_setopt($ch, CURLOPT_URL, $url); // 要访问的地址
if ($is_ssl) {
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); // 对认证证书来源的检查
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); // 从证书中检查SSL加密算法是否存在
curl_setopt($ch, CURLOPT_SSLVERSION, 1); // 设定SSL版本,微信时候使用1,否则报错
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
}
if ($data) {
curl_setopt($ch, CURLOPT_POST, 1); // 发送一个常规的Post请求
curl_setopt($ch, CURLOPT_POSTFIELDS, $data); // Post提交的数据包
}
$header[]= "Sercet: edf_a3d1bf7760f3485aa2f7bd4a3124db71";
$header[]= "Time: ".date('YmdHis');
if ($header) {
curl_setopt($ch,CURLOPT_HTTPHEADER,$header);
}
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回
$out = curl_exec($ch);
$outArr = json_decode($out, true);
if($outArr) {
return $outArr;
} else {
return $out;
}
}
function aaa() {
return $GLOBALS['config']['img_path'];
}
function db($config) {
//创建新连接
$con = new mysqli($config['DB_HOST'],$config['DB_USER'],$config['DB_PWD'],$config['DB_NAME'],$config['DB_PORT']);
if($con){
$con->set_charset("utf8");
return $con;
}else{
echo("connect database is error!!".$con->connect_error);
return false;
}
}
function cache($config) {
$con = new Redis();
$con->connect($config['host'], $config['port']);
if(!empty($config['auth'])){
$this->auth($config['auth']);
}
return $con;
}
\ No newline at end of file
<?php
$GLOBALS['config'] = array(
'REDIS'=>array(
'type'=>'Redis',
'host'=>'127.0.0.1', // 119.23.249.188 (部署)
'port'=>'6379',
'auth'=>''
),
'MYSQL' => array(
'DB_TYPE' => 'mysql',
'DB_HOST' => '127.0.0.1',
'DB_NAME' => 'lewan_hezi',
'DB_USER' => 'root',
'DB_PWD' => '1QAZ2wsx',
'DB_PORT' => '3306',
'DB_PREFIX' => '',
'DB_CHARSET' => 'utf8',
),
'socket_controller' => 'application/socket/controller/',
'img_path'=> '/9999/'
);
\ No newline at end of file
<?php
class base {
public $server;
public $fd;
public $reqData;
public function setData($data)
{
if(!empty($data['server']) && !empty($data['fd']) && !empty($data['d'])) {
$this->server = $data['server'];
$this->fd = $data['fd'];
$this->reqData = $data['d'];
return true;
} else {
return false;
}
}
}
\ No newline at end of file
<?php
include_once("application/socket/model/UserModel.php");//uesrModel
class user extends base {
public function getData()
{
$userModel = new \socket\model\UserModel();
$data = $userModel->test();
$reData = json_encode(array('c'=>1,'msg'=>'success','d'=>array('list'=>$data)));
$this->server->push($this->fd, $reData);
}
public function login() {
if(empty($this->reqData['uid'])) {
$result = array(
'c'=>2
,'msg'=>$this->reqData['uid']
);
} else {
$GLOBALS['USER_LIST']->set($this->reqData['uid'],array('fd'=>$this->fd));
$result = array(
'c'=>1
,'msg'=>'登录成功'
);
}
$this->server->push($this->fd, json_encode($result));
}
public function info() {
$data = post_curl('http://ylc.test.llewan.com/shop/goodsList',array('id'=>65421));
$this->server->push($this->fd, json_encode($data));
return 'success';
}
public function cache() {
$data = $GLOBALS['redisDB']->get('hezijp001');
//$reData = json_encode(array('c'=>1,'msg'=>'success','d'=>array('list'=>$data)));
$this->server->push($this->fd, 9999);
}
public function msg() {
if(empty($this->reqData['uid'])) {
$result = array(
'c'=>2
,'msg'=>'uid参数不存在'
);
} else {
$fd = $GLOBALS['USER_LIST']->get($this->reqData['uid'])['fd'];
if(!empty($fd)) {
$this->fd = $fd;
$result = array(
'c'=>1
,'msg'=>'发送成功'
,'d'=>array('text'=>$this->reqData['text'])
);
} else {
$result = array(
'c'=>2
,'msg'=>'uid参数错误'
);
}
}
$this->server->push($this->fd, json_encode($result));
}
}
\ No newline at end of file
<?php
namespace socket\model;
class BaseModel {
public function __construct() {
//code
}
}
\ No newline at end of file
<?php
namespace socket\model;
include_once("application/socket/model/BaseModel.php");//uesrModel
use socket\model\BaseModel;
class UserModel extends BaseModel {
public function test()
{
$data = $GLOBALS['mysqlDB']->select('*')->from('game_member_login_log')->limit(10)->query();
return $data;
}
}
\ No newline at end of file
This diff is collapsed.
<?php
//在线用户列表
$GLOBALS['USER_LIST'] = new swoole_table(20480);
$GLOBALS['USER_LIST']->column('fd', swoole_table::TYPE_INT, 4);
$GLOBALS['USER_LIST']->create();
//在线用户连接列表
$GLOBALS['USER_LIST_FD'] = new swoole_table(20480);
$GLOBALS['USER_LIST_FD']->column('uid', swoole_table::TYPE_STRING, 15);
$GLOBALS['USER_LIST_FD']->create();
//任务数
$GLOBALS["TASK_LIST"] = new swoole_table(20480);
$GLOBALS['TASK_LIST']->column('task',swoole_table::TYPE_INT, 8);
$GLOBALS['TASK_LIST']->create();
// 引入socketServer文件
require './swoole/socketServer.php';
$server = new socketServer("0.0.0.0","9501");
\ No newline at end of file
<?php
class socketServer
{
private $server;
public $handle;
public function __construct($host,$port) {
$this->server = new swoole_websocket_server($host, $port);
$this->server->set(array(
'open_tcp_nodelay' => 1,
'open_cpu_affinity' => 1,
'task_worker_num' =>8,
'dispatch_mode'=>2,
'daemonize' => 0,//守护进程化。设置daemonize => 1时,程序将转入后台作为守护进程运行。长时间运行的服务器端程序必须启用此项。
'reactor_num' => 2,//2个处理线程的数量
'worker_num' => 4,//4个线程
'max_request' => 0,//最大10万个连接请求
// 'heartbeat_idle_time' => 60,//如果客户端超过600秒未向服务器发消息
// 'heartbeat_check_interval' =>61,//每60秒检查一次所有的连接
'log_file' => './swoole.log'
));
$this->server->on('start', array($this, 'onStart'));
$this->server->on('shutdown', array($this, 'onShutdown'));
$this->server->on('workerStart', array($this, 'onWorkerStart'));
$this->server->on('workerStop', array($this, 'onWorkerStop'));
$this->server->on('workerError', array($this, 'onWorkerError'));
$this->server->on('open', array($this, 'onOpen'));
$this->server->on('message', array($this, 'onMessage'));
$this->server->on('request', array($this, 'onRequest'));
$this->server->on('task', array($this, 'onTask'));
$this->server->on('finish', array($this, 'onFinish'));
$this->server->on('close', array($this, 'onClose'));
$this->server->start();
}
//Server启动在主进程的主线程回调此函数
public function onStart( $server ) {
// cli_set_process_title("ws_server1");
}
//此事件在Server正常结束时发生
public function onShutdown( $server ) {
//$this->_echo_log(__CLASS__."->".__FUNCTION__."\r\n");
}
//此事件在Worker进程时发生(加载socket业务文件)
public function onWorkerStart( $server , $worker_id) {
require_once "./swoole/socketWork.php";
$this->handle = new socketWork($server);
}
//此事件在worker进程终止时发生
public function onWorkerStop( $server , $worker_id) {
$this->handle->onWorkerStop($server, $worker_id);
}
//当worker/task_worker进程发生异常后会在Manager进程内回调此函数
public function onWorkerError( $server , $worker_id) {
$this->handle->onWorkerError($server, $worker_id);
}
//websocket客户端链接回调
public function onOpen( $server , $request) {
$this->handle->onOpen($server, $request);
}
//websocket客户端发送消息回调
public function onMessage( $server, $frame) {
$this->handle->onMessage($server, $frame);
}
//http访问回调
public function onRequest( $request, $response) {
$this->handle->onRequest($this->server,$request, $response);
}
//在task_worker进程内被调用
public function onTask($server,$task_Id, $worker_id, $data){
$this->handle->onTask($server, $task_Id, $worker_id, $data);
}
//当worker进程投递的任务在task_worker中完成时
public function onFinish($server,$task_Id, $data){
$this->handle->onFinish($server,$task_Id, $data);
}
//客户端连接关闭
public function onClose($server, $fd) {
$this->handle->onClose($server, $fd);
}
}
\ No newline at end of file
<?php
include_once("application/config.php");//配置信息
include_once("application/common.php");//公共方法
include_once("extend/mysql/Connection.php");//mysql方法
class socketWork {
public $server;
public $userTable = 'user_info';
public function __construct($server) {
$this->server = $server;
//链接数据库
$GLOBALS['redisDB'] = cache($GLOBALS['config']['REDIS']);
$GLOBALS['mysqlDB'] = new \Workerman\MySQL\Connection($GLOBALS['config']['MYSQL']['DB_HOST'], $GLOBALS['config']['MYSQL']['DB_PORT'], $GLOBALS['config']['MYSQL']['DB_USER'], $GLOBALS['config']['MYSQL']['DB_PWD'], $GLOBALS['config']['MYSQL']['DB_NAME']);
}
public function onWorkerStop( $server , $worker_id) {
if ($GLOBALS['redisDB']) {
$GLOBALS['redisDB']->close();
}
if ($GLOBALS['mysqlDB']) {
$GLOBALS['mysqlDB']->closeConnection();
}
}
public function onWorkerError( $server , $worker_id) {
echo _log('work进程报错');
}
public function onOpen($server, $frame) {
$uid = 'fd'.$frame->fd;
$GLOBALS['USER_LIST']->set($uid,array('fd'=>$frame->fd));
$server->push($frame->fd, "你好:$uid");
}
public function onMessage($server, $frame) {
$data = json_decode($frame->data,true);
// $path = 'application/socket/'.$data['m'].'.php';
if (class_exists($data['m'])) {
$data['fd'] = $frame->fd;
$data['ip'] = $this->server->connections[$frame->fd]['remote_ip'];
$tmp_task_id = $this->server->task($data);
echo_log("进行task任务:".$tmp_task_id);
}else{
$server->push($frame->fd, "找不到对应的模块");
}
}
public function onRequest($server, $request, $response) {
$event = $request->get['event'];
if($event == 'reload') {
$server->reload();
$response->write('reload success');
}else if($event == 'sendAll') {
$this->sendAll($server,'大家好');
$response->write($GLOBALS['USER_LIST']->get('fd3'));
} else {
// $data = $this->server->db->select('sysid as id,name')->from('yl_goods')->where('sysid=1')->row();
// $reData = json_encode(array('c'=>1,'msg'=>'success','d'=>array('list'=>$data)));
$response->write($GLOBALS['redisDB']->get('hezijp001'));
}
}
public function onTask($server, $task_Id, $worker_id, $data) {
echo_log("进行task任务:".$task_Id.'开始工作');
$act = new $data['m']();
//是否有这个方法在
if (!method_exists($act, $data['a'])) {
$server->push($frame->fd, "找不到对应的方法");
$this->server->finish($task_Id);
return false;
} else {
$data['server'] = $server;
if($act->setData($data)){
echo_log("执行情况:".$act->{$data['a']}() );
$this->server->finish($task_Id);
return true;
}else{
echo_log("执行出错:".$data['m']."->".$data['a']."\r\n");
$this->server->finish($task_Id);
return false;
}
}
}
public function onFinish($server,$task_Id, $data) {
echo_log("进行task任务:".$task_Id.'工作完成');
}
public function onClose($server, $fd) {
$GLOBALS['USER_LIST']->del('fd'.$fd);
echo 'client'.$fd.'下线';
//$this->redis->hdel($this->userTable,"fd{$fd}");
//$this->sendAll($server,"用户{$fd}下线了");
}
//根据用户ID查用户的连接记录
public function get_user_by_uid($uid){
echo_log(__CLASS__."->".__FUNCTION__."\r\n");
if($GLOBALS['USER_LIST']->exist($uid)){
$tmp_val = $GLOBALS['USER_LIST']->get($uid);
return $tmp_val;
}else{
return false;
}
}
//根据用户的fd查用户的uid
public function get_user_by_fd($fd){
echo_log(__CLASS__."->".__FUNCTION__."\r\n");
if($GLOBALS['USER_LIST_FD']->exist($fd)){
$tmp_val = $GLOBALS['USER_LIST_FD']->get($fd);
return $tmp_val;
}else{
return false;
}
}
//设置用户在线
/*
$data = array(
"fd" => ,//"连接",
"uid" => ,//用户ID,
);
*/
public function set_user_list($data){
//删掉这个uid之前绑定的连接
$tmp_uid = $GLOBALS['USER_LIST']->get($data['uid']);
if($tmp_uid && $tmp_uid['fd']>0){
$GLOBALS['USER_LIST_FD']->del($tmp_uid['fd']);
$GLOBALS['USER_LIST']->del($data['uid']);
}
$GLOBALS['USER_LIST']->set($data['uid'],array('fd'=>$data['fd']));
$GLOBALS['USER_LIST_FD']->set($data['fd'],array('uid'=>$data['uid']));
return true;
}
//给某个用户发信息
public function send_user($fd,$data,$opcode=1,$finish=true){
echo_log(__CLASS__."->".__FUNCTION__."\r\n");
if(empty($fd)){
return false;
}
if(is_array($data)){
$data = return_ajax($data);
echo $data;
}
//检测通道是否存在
if(!$this->server->exist($fd)){
echo_log("通道[ $fd ]的客户端已经断开,无法发送消息!\r\n",$data);
unset($data);
return false;
}else{
$this->server->push($fd,$data,$opcode,$finish);
unset($data);
return $finish;
}
}
//给指定用户发信息
public function send_all($arr,$data,$opcode=1,$finish=true){
echo_log(__CLASS__."->".__FUNCTION__."\r\n");
if(!empty($arr)){
foreach($arr as $uid){
if($GLOBALS['USER_LIST']->exist($uid)){
$tmp_fd = $GLOBALS['USER_LIST']->get($uid);
if($this->send_user($tmp_fd['fd'],$data,$opcode,$finish)){
echo_log('用户['. $uid .']发送消息成功!\r\n');
}else{
echo_log('用户['. $uid .']的客户端已经断开,无法发送消息!\r\n');
}
}
}
}else{
echo_log('没有指定要发信息的用户,无法发送消息!\r\n');
}
return true;
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment