From 4a71b8b7fd4497e9d689e3c0eecfc35f7b5558eb Mon Sep 17 00:00:00 2001
From: zhoudw <zhoudw@infobird.com>
Date: Tue, 21 Dec 2021 14:06:31 +0800
Subject: [PATCH] task
---
config/config.php | 23 +++
.gitignore | 3
config/dev.php | 0
config/pro.php | 0
index.html | 75 ++++++++++++
logs/test.log | 1
start.sh | 2
ws_server.php | 239 +++++++++++++++++++++++++++++++++++++++
config/test.php | 0
9 files changed, 343 insertions(+), 0 deletions(-)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..104fbb9
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+.DS_Store
+logs/*/
+ws.out
\ No newline at end of file
diff --git a/config/config.php b/config/config.php
new file mode 100644
index 0000000..aaccd7a
--- /dev/null
+++ b/config/config.php
@@ -0,0 +1,23 @@
+<?php
+/*
+ * @Author: your name
+ * @Date: 2021-12-15 11:33:00
+ * @LastEditTime: 2021-12-21 13:40:02
+ * @LastEditors: Please set LastEditors
+ * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ * @FilePath: /websocket/config/config.php
+ */
+return array(
+ //WebSocket绑定、分组、在线等信息存储使用的Redis配置
+ 'redis' => array(
+ 'host' => '120.76.101.87',
+ 'port' => '51101'
+ ),
+ //本机WebSocket服务配置
+ 'server_config' => array(
+ 'allow_ip' => '120.25.156.26:58003',
+ 'host' => '0.0.0.0',
+ 'port' => '9501',
+ ),
+
+);
diff --git a/config/dev.php b/config/dev.php
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/config/dev.php
diff --git a/config/pro.php b/config/pro.php
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/config/pro.php
diff --git a/config/test.php b/config/test.php
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/config/test.php
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..f204e5f
--- /dev/null
+++ b/index.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<head>
+ <title>socket demo</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <script type="text/javascript" src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
+</head>
+<body>
+<input type="text" id="msg" />
+<button id="send">发送</button>
+</body>
+</html>
+<script>
+ $(function()
+ {
+ // 创建socket对象
+ var socket = new WebSocket('ws://127.0.0.1:9501');
+
+ // 打开Socket
+ socket.onopen = function(event)
+ {
+
+ $('#send').on('click', function()
+ {
+ var msg = $('#msg').val();
+ var url = 'application/index/data';
+ var fullData = {
+ url:url,
+ data:{
+ session_id:'1a2e0ca9c7404b765a37a5ab07546fa8',
+ group_id:'1a2e0ca9c7404b765a37a5ab07546fa8',
+ msg:msg
+ }
+ };
+ socket.send(JSON.stringify(fullData));
+ console.log(msg);
+ });
+ var url = 'application/index/reg';
+ var fullData = {
+ url:url,
+ data:{
+ session_id:'1a2e0ca9c7404b765a37a5ab07546fa8',
+ group_id:'1a2e0ca9c7404b765a37a5ab07546fa8'
+ }
+ };
+ // 发送一个初始化消息
+ socket.send(JSON.stringify(fullData));
+ if (socket.readyState == 1) {
+ setInterval(function(){
+ var fullData = {
+ url: 'plumeWSService/cluster/ping',
+ data: 'ping'
+ };
+ socket.send(JSON.stringify(fullData));
+ },1000)
+ }
+ // 监听消息
+ socket.onmessage = function(event) {
+ if(event.data == 'pingpong'){//处理心跳接收事件
+
+ }else{
+ var fullData = JSON.parse(event.data);
+ console.log("客户端监听到的消息:", fullData);
+ }
+ };
+
+ // 监听Socket的关闭
+ socket.onclose = function(event) {
+ console.log("Socket关闭了", event);
+ };
+
+ // 关闭Socket....
+ //socket.close()
+ };
+ });
+</script>
\ No newline at end of file
diff --git a/logs/test.log b/logs/test.log
new file mode 100644
index 0000000..d979aad
--- /dev/null
+++ b/logs/test.log
@@ -0,0 +1 @@
+日志
\ No newline at end of file
diff --git a/start.sh b/start.sh
new file mode 100644
index 0000000..e70a8a2
--- /dev/null
+++ b/start.sh
@@ -0,0 +1,2 @@
+#!/bin/bash
+php ws_server.php
\ No newline at end of file
diff --git a/ws_server.php b/ws_server.php
new file mode 100644
index 0000000..6c22850
--- /dev/null
+++ b/ws_server.php
@@ -0,0 +1,239 @@
+<?php
+/*
+ * @Author: zhoudw
+ * @Date: 2021-12-13 09:57:20
+ * @Last Modified by: zhoudw
+ * @Last Modified time: 2021-12-13 09:58:34
+ */
+class ws_server
+{
+
+ protected $server;
+ protected $request;
+ protected $frame;
+ protected $server_config;
+ protected $redis = null;
+ protected $redis_config;
+ public function __construct()
+ {
+ $config = require './config/config.php';
+ $this->server_config = $config['server_config'];
+ $this->redis_config = $config['redis'];
+
+ $this->server = new Swoole\WebSocket\Server($this->server_config['host'], $this->server_config['port']); // swoole连接
+ $this->server->set([
+ 'task_worker_num' => 8,
+ 'enable_coroutine' => true,
+ 'task_enable_coroutine' => true
+ ]);
+ if (!$this->redis) {
+ $this->redis = new Redis();
+ }
+ $this->server->on('start', function (Swoole\WebSocket\Server $server) {
+ echo "Websocket Server is started at ws://".$this->server_config['host'].":".$this->server_config['port']."\n";
+ });
+
+ $this->server->on('message', function (Swoole\WebSocket\Server $server, $frame) {
+ $server->task($frame);
+ // $ret = array('code' => 0, 'data' => null);
+ // $msgData = $this->is_json($frame->data,true);
+ // if($msgData){
+ // $frameData = $msgData;
+ // $this->dealMsg($frameData,$frame->fd);
+ // }else{
+ // $ret['code'] = -1;
+ // $ret['msg'] = 'data is null or data no json';
+ // $server->push($frame->fd, json_encode($ret));
+ // return;
+ // }
+ });
+
+ $this->server->on('task', function ($server, $task) {
+ $ret = array('code' => 0, 'data' => null);
+ $frame = $task->data;
+ $msgData = $this->is_json($frame->data,true);
+ if($msgData){
+ $frameData = $msgData;
+ $this->dealMsg($frameData,$frame->fd);
+ }else{
+ $ret['code'] = -1;
+ $ret['msg'] = 'data is null or data no json';
+ $server->push($frame->fd, json_encode($ret));
+ return;
+ }
+ });
+ $this->server->on('close', function ($ser, $fd) {
+ $host = $this->server_config['allow_ip'];
+ $this->redis->connect($this->redis_config['host'],$this->redis_config['port'] );
+ $group_key = $this->redis->get($host.':'.$fd.':group');
+ $this->redis->lrem($group_key,$fd,0);
+ });
+
+ $this->server->start();
+
+ }
+
+ /**
+ * 功能:1、判断是否是json
+ * @param string $data
+ * @param bool $assoc
+ * @return bool|mixed|string
+ */
+ function is_json($data = '', $assoc = false)
+ {
+ $data = json_decode($data, $assoc);
+ if ($data && (is_object($data)) || (is_array($data) && ! empty(current($data)))) {
+ return $data;
+ }
+ return false;
+ }
+
+ /**
+ * 功能:1、消息处理
+ */
+ public function dealMsg($msgContent,$fd){
+ $ret = array('code' => 0, 'data' => null);
+ // $this->server->push($fd,json_encode($ret));
+ $url = $msgContent['url'];
+ $data = $msgContent['data'];
+ $action = substr($url, strrpos($url, "/") + 1);
+ $this->log('action','ws','ws',$action);
+ switch ($action)
+ {
+ case "reg":
+ $this->log('reg','reg','ws',['content'=>$msgContent,'fd'=>$fd]);
+ $groupId = $data['group_id'];
+ $session = $data['session_id'];
+ $this->bind($groupId,'',$fd);
+ $key = "practice_scenes_ws_cur_session_info:".$session;
+ $node_key = 'practice_scenes_ws_cur_session_node_info:'.$session;
+ $redisData = $this->redis->get($key);
+ if($redisData){
+ $ret['data'] =json_decode($redisData,true);
+ $this->redis->del($key);
+ }else{
+ $redisData = $this->redis->get($node_key);
+ $ret['data'] =json_decode($redisData,true);
+ }
+ $ret['event'] = "re_bind";
+ $this->replay($fd,$ret);
+ break;
+ case "data":
+ $this->log('data','data','ws',['content'=>$msgContent,'fd'=>$fd]);
+ $groupId = $data['group_id'];
+ $ret['event'] = "data";
+ $ret['data'] = $data;
+ $this->broadcastself($ret , $groupId);
+ break;
+ case "ping":
+ $this->replay($fd,$data.'pong', false);
+ break;
+ default:
+ $ret['code'] = 404;
+ $ret['msg'] = 'event no existent';
+ $this->server->push($fd,json_encode($ret));
+ return;
+ }
+ }
+
+
+ /**
+ * 当前链接的绑定事件。
+ * 绑定的几种状态:
+ * 1.无分组
+ * host -> fds (获取当前节点的在线链接列表)
+ * host:fd -> value (获取当前节点当前链接的绑定数据)
+ * host:fd:group -> host (获取当前节点当前链接的绑定分组)
+ * 2.有分组
+ * groupID:host -> fds
+ * host:fd -> value
+ * host:fd:group -> groupID:host
+ * @param string $groupID 需要绑定当前链接所在分组的分组标识,如果为空则使用默认分组
+ * @param string $value 需要绑定当前链接对应的业务数据,如果为空则不绑定
+ */
+ public function bind($groupID = '', $value = '',$fd){
+ $this->redis->connect($this->redis_config['host'],$this->redis_config['port'] );
+ $host = $this->server_config['allow_ip'];
+ // 绑定分组和当前链接对应的分组标识
+ if(empty($groupID)){
+ $this->redis->rpush($host, $fd);
+ $this->redis->set($host.':'.$fd.':group', $host);
+ }else{
+ $this->redis->rpush($groupID.':'.$host, $fd);
+ $this->redis->set($host.':'.$fd.':group', $groupID.':'.$host);
+ }
+ // 绑定业务数据
+ if(!empty($value)){
+ $this->redis->set($host.':'.$fd, $value);
+ }
+ }
+
+ /**
+ * 对指定数据和分组对当前集群节点进行广播。
+ * @param \stdClass $data 广播数据
+ * @param string $groupID 分组标识
+ */
+ public function broadcastself($data, $groupID = '') {
+ $host = $this->server_config['allow_ip'];
+ $connections = array();
+ if(empty($groupID)){
+ // 获取所有无分组标识在线终端
+ $onlines = count($this->server->connections);
+ if ($onlines > 0) {
+ $connections = $this->server->connections;
+ }
+ }else{
+ // 获取所有分组标识在线终端 key = groupID:host
+ $key = $groupID . ':' . $host;
+ try {
+ $this->redis->connect($this->redis_config['host'],$this->redis_config['port'] );
+ $connections = $this->redis->lrange($key, 0, -1);
+ if (!is_array($connections)) {//redis异常
+ $this->log('redis异常','ws','broadcastself',['key'=>$key,'data'=>$data]);
+ return;
+ }
+ } catch (\Exception $e) {
+ $this->log('redis异常','ws','broadcastself',['key'=>$key,'data'=>$data,'msg'=>$e->getMessage()]);
+ return;
+ }
+ }
+ if(is_array($data)){
+ $data['group_id'] = $groupID;
+ }else{
+ $data->group_id = $groupID;
+ }
+ $connections = array_unique($connections);
+ // 广播获取的在线终端
+ foreach ($connections as $fd) {
+ $this->server->push($fd,json_encode($data));
+ }
+ }
+ /**
+ * 回复当前链接。
+ * @param \stdClass $data 回复数据
+ * @param bool $encode 如果$data是string格式,则encode为false
+ */
+ public function replay($fd,$data,$encode = true) {
+ $json_data = $data;
+ if($encode){
+ $json_data = json_encode($data, JSON_UNESCAPED_UNICODE);
+ }
+ $this->server->push($fd, $json_data);
+ }
+
+ function log($title,$folder,$finename,$msg)
+ {
+ $logs = json_encode($msg);
+ $msg = "[".date('Y-m-d H:i:s')."]\t- INFO - ".$title." - ".$logs."\n";
+ //判断目的文件夹是否存在? 如果不存在就生成
+ //简单处理: 实际应用需要修改
+ $dst ='./logs/'.$folder;
+ if (is_dir($dst) === FALSE) {
+ @mkdir($dst, 0777, true);
+ }
+ $log_file_name = $dst.'/'.$finename.'-'.date('Y-m-d').'.log';
+ return @file_put_contents($log_file_name, $msg, FILE_APPEND);
+ }
+}
+$ws = new ws_server();
+?>
\ No newline at end of file
--
Gitblit v1.8.0