feat: 实现TCP Server

This commit is contained in:
zimoyin
2026-03-02 21:59:43 +08:00
parent 043306819b
commit a79dfae57d
144 changed files with 15785 additions and 140 deletions
+26
View File
@@ -0,0 +1,26 @@
<?php
/**
* This file is part of webman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
use support\Request;
return [
'debug' => true,
'error_reporting' => E_ALL,
'default_timezone' => 'Asia/Shanghai',
'request_class' => Request::class,
'public_path' => base_path() . DIRECTORY_SEPARATOR . 'public',
'runtime_path' => base_path(false) . DIRECTORY_SEPARATOR . 'runtime',
'controller_suffix' => 'Controller',
'controller_reuse' => false,
];
+21
View File
@@ -0,0 +1,21 @@
<?php
/**
* This file is part of webman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
return [
'files' => [
base_path() . '/app/functions.php',
base_path() . '/support/Request.php',
base_path() . '/support/Response.php',
]
];
+19
View File
@@ -0,0 +1,19 @@
<?php
/**
* This file is part of webman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
return [
support\bootstrap\Session::class,
Webman\ThinkOrm\ThinkOrm::class,
app\bootstrap\SqlDebug::class,
];
+15
View File
@@ -0,0 +1,15 @@
<?php
/**
* This file is part of webman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
return new Webman\Container;
+32
View File
@@ -0,0 +1,32 @@
<?php
use app\config\Config;
return [
'default' => 'mysql',
'connections' => [
'mysql' => [
'driver' => 'mysql',
'host' => Config::getStringEnv('DB_HOST', 'localhost'),
'port' => Config::getIntEnv('DB_PORT',3306),
'database' => Config::getStringEnv('DB_NAME', 'opm_ectms'),
'username' => Config::getStringEnv('DB_USER', 'root'),
'password' => Config::getStringEnv('DB_PASSWORD'),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_general_ci',
'prefix' => '',
'strict' => true,
'engine' => null,
'options' => [
PDO::ATTR_EMULATE_PREPARES => false, // Must be false for Swoole and Swow drivers.
],
'pool' => [
'max_connections' => 5,
'min_connections' => 1,
'wait_timeout' => 3,
'idle_timeout' => 60,
'heartbeat_interval' => 50,
],
],
],
];
+15
View File
@@ -0,0 +1,15 @@
<?php
/**
* This file is part of webman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
return [];
+17
View File
@@ -0,0 +1,17 @@
<?php
/**
* This file is part of webman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
return [
'' => support\exception\Handler::class,
];
+217
View File
@@ -0,0 +1,217 @@
<?php
use Monolog\Logger;
use Monolog\Handler\RotatingFileHandler;
use Monolog\Handler\StreamHandler;
use Monolog\Handler\FilterHandler;
use Monolog\Processor\ProcessIdProcessor;
use app\config\Config;
return [
'default' => [
'handlers' => [
// 控制台输出处理器
[
'class' => StreamHandler::class,
'constructor' => [
'php://stdout',
Config::getInstance()->logLevel,
],
'formatter' => [
'class' => Monolog\Formatter\LineFormatter::class,
/**
* 格式化日志输出
* %start%: 标记日志颜色
* %end%: 结束标记颜色
* %logger%: 日志记录器名称
* %L: 行号
* %M: 方法名
* %P: 进程ID
* %thread%: 线程ID
* %Level%: 日志级别(带有占位符)
* %level_name%: 日志级别名称
* %level%: 日志等级数字
* %message%: 日志内容
* %datetime%: 时间
*/
'constructor' => [
"%start%%datetime% [%thread%] %Level% %logger%:%L% - %message%%end%\n",
'Y-m-d H:i:s',
true
],
],
],
// 默认文件输出处理器
[
'class' => RotatingFileHandler::class,
'constructor' => [
runtime_path() . '/logs/webman.log',
Config::getInstance()->logRotationTimeByDay,
Config::getInstance()->logLevel,
],
'formatter' => [
'class' => Monolog\Formatter\LineFormatter::class,
'constructor' => [
"%datetime% [%thread%] %Level% %logger%:%L% - %message%\n",
'Y-m-d H:i:s',
true
],
],
],
// Error级别单独文件处理器
[
'class' => FilterHandler::class,
'constructor' => [
new RotatingFileHandler(
runtime_path() . '/logs/error.log',
Config::getInstance()->errorLogRotationTimeByDay,
Logger::DEBUG
),
Logger::ERROR,
Logger::EMERGENCY
],
'formatter' => [
'class' => Monolog\Formatter\LineFormatter::class,
'constructor' => [
"%datetime% [%thread%] %Level% %logger%:%L% - %message%\n",
'Y-m-d H:i:s',
true
],
],
],
],
// 全局处理器:手动解析调用栈,精准定位业务代码
'processors' => [
// 1. 注入进程ID(生成线程名)
new ProcessIdProcessor(),
// 2. 手动解析调用栈,获取实际业务代码位置 + 日志过滤
function ($record) {
$message = $record['message'];
// 线程名
$processId = $record['extra']['process'] ?? 0;
$record['thread'] = "thread-{$processId}";
// 手动解析调用栈,定位实际业务代码
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 10); // 获取调用栈(前10层)
$file = $record['channel'];
$function = '';
$line = '0';
// 遍历调用栈,跳过日志类相关的层,找到业务代码层
foreach ($trace as $step) {
// 跳过 webman 日志类、monolog 相关的调用层
if (isset($step['file'])
&& str_contains($step['file'], 'support') === false
&& str_contains($step['file'], 'monolog') === false
&& str_contains($step['file'], 'Logger') === false
) {
// 获取文件路径(简化为项目内相对路径)
$file = $step['file'];
$projectRoot = base_path();
if (str_starts_with($file, $projectRoot)) {
$file = substr($file, strlen($projectRoot) + 1);
}
$file = str_replace('.php', '', $file);
$file = str_replace('\\', '.', $file);
// 获取方法名
$function = $step['function'];
// 获取行
$line = $step['line'] ?? '0';
break; // 找到第一个业务代码层就停止
}
}
$record['M'] = $function;
$record['L'] = $line;
$record['P'] = $record['extra']['process_id'];
// 解析 <RP_NAME:xxx> 标签
$pattern = '/<RP_NAME:(.*?)>/si';
if (preg_match_all($pattern, $message, $matches) && !empty($matches[1])) {
$record['logger'] = $matches[1][0];
$record['message'] = preg_replace($pattern, '', $message);
if ($matches[1][0] == '__default') $record['logger'] = $file;
} else {
$record['logger'] = $file;
$record['message'] = $message;
}
// 解析 SQL_LOG 相关标签
$tagPatterns = [
'logger' => '/<SQL_LOG_F>(.*?)<\/SQL_LOG_F>/s', // 文件路径
'L' => '/<SQL_LOG_L>(.*?)<\/SQL_LOG_L>/s', // 行号
'M' => '/<SQL_LOG_M>(.*?)<\/SQL_LOG_M>/s' // 方法名
];
$tempMessage = $record['message']; // 基于处理后的message继续解析
foreach ($tagPatterns as $key => $pattern) {
if (preg_match($pattern, $tempMessage, $matches)) {
$record[$key] = $matches[1];
$tempMessage = preg_replace($pattern, '', $tempMessage); // 移除当前标签
$record['message'] = trim($tempMessage);
}
}
// 日志级别颜色映射
$levelColorMap = [
Logger::EMERGENCY => "\033[41m\033[37m", // 最高级别:红色底色+白色字体
Logger::ALERT => "\033[41m\033[37m", // 警报:红色底色+白色字体
Logger::CRITICAL => "\033[41m\033[37m", // 严重:红色底色+白色字体
Logger::ERROR => "\033[31m", // 错误:红色字体(无底色)
Logger::WARNING => "\033[33m", // 警告:深黄色字体
Logger::INFO => "\033[32m", // 信息:绿色字体
Logger::DEBUG => "\033[34m", // 调试:蓝色字体
];
$record['start'] = "\033[0m";
$record['end'] = "\033[0m";
foreach ($levelColorMap as $level => $color) {
if ($record['level'] >= $level) {
$record['start'] = $color;
$record['end'] = "\033[0m";
break;
}
}
$record['Level'] = str_pad(strtoupper($record['level_name']), 5);
$logFilter = Config::getInstance()->logFilter;
$matchWildcard = function (string $pattern, string $value): bool {
// 空规则特殊处理:如:debug 拆分后类规则为空,代表匹配所有类
if ($pattern === '') {
return true;
}
// 将通配符*转换为正则的.*,并转义其他特殊字符
$regexPattern = preg_quote($pattern, '/');
$regexPattern = str_replace('\*', '.*', $regexPattern);
// 正则全程匹配
return preg_match('/^' . $regexPattern . '$/', $value) === 1;
};
if (!empty($logFilter)) {
$className = $record['logger'] ?? '';
$methodName = $record['M'] ?? '';
// 遍历过滤规则,匹配则返回null(过滤日志)
foreach ($logFilter as $filter) {
// 拆分规则为类规则和方法规则(最多拆2部分,避免方法名含:)
[$filterClassRule, $filterMethodRule] = array_pad(explode(':', $filter, 2), 2, '*');
// 匹配类名规则(支持通配符*
$isClassMatch = $matchWildcard($filterClassRule, $className);
// 匹配方法名规则(支持通配符*
$isMethodMatch = $matchWildcard($filterMethodRule, $methodName);
// 类和方法都匹配时,过滤该日志
if ($isClassMatch && $isMethodMatch) {
return null;
}
}
}
return $record;
}
],
],
];
+15
View File
@@ -0,0 +1,15 @@
<?php
/**
* This file is part of webman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
return [];
+28
View File
@@ -0,0 +1,28 @@
<?php
return [
'enable' => true,
'build_dir' => BASE_PATH . DIRECTORY_SEPARATOR . 'build',
'phar_filename' => 'webman.phar',
'phar_format' => Phar::PHAR, // Phar archive format: Phar::PHAR, Phar::TAR, Phar::ZIP
'phar_compression' => Phar::NONE, // Compression method for Phar archive: Phar::NONE, Phar::GZ, Phar::BZ2
'bin_filename' => 'webman.bin',
'signature_algorithm'=> Phar::SHA256, //set the signature algorithm for a phar and apply it. The signature algorithm must be one of Phar::MD5, Phar::SHA1, Phar::SHA256, Phar::SHA512, or Phar::OPENSSL.
'private_key_file' => '', // The file path for certificate or OpenSSL private key file.
'exclude_pattern' => '#^(?!.*(composer.json|/.github/|/.idea/|/.git/|/.setting/|/runtime/|/vendor-bin/|/build/|/vendor/webman/admin/))(.*)$#',
'exclude_files' => [
'.env', 'LICENSE', 'composer.json', 'composer.lock', 'start.php', 'webman.phar', 'webman.bin'
],
'custom_ini' => '
memory_limit = 256M
',
];
+67
View File
@@ -0,0 +1,67 @@
<?php
/**
* This file is part of webman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
use app\config\Config;
use support\Log;
use support\Request;
use app\process\Http;
global $argv;
return [
'webman' => [
'handler' => Http::class,
'listen' => 'http://0.0.0.0:8787',
'count' => cpu_count() * 4,
'user' => '',
'group' => '',
'reusePort' => false,
'eventLoop' => '',
'context' => [],
'constructor' => [
'requestClass' => Request::class,
'logger' => Log::channel('default'),
'appPath' => app_path(),
'publicPath' => public_path()
]
],
// File update detection and automatic reload
'monitor' => [
'handler' => app\process\Monitor::class,
'reloadable' => false,
'constructor' => [
// Monitor these directories
'monitorDir' => array_merge([
app_path(),
config_path(),
base_path() . '/process',
base_path() . '/support',
base_path() . '/resource',
base_path() . '/.env',
], glob(base_path() . '/plugin/*/app'), glob(base_path() . '/plugin/*/config'), glob(base_path() . '/plugin/*/api')),
// Files with these suffixes will be monitored
'monitorExtensions' => [
'php', 'html', 'htm', 'env'
],
'options' => [
'enable_file_monitor' => !in_array('-d', $argv) && DIRECTORY_SEPARATOR === '/',
'enable_memory_monitor' => DIRECTORY_SEPARATOR === '/',
]
]
],
'TcpServer' => [
'handler' => app\process\TcpServer::class,
'listen' => 'tcp://0.0.0.0:'. Config::getStringEnv("TCP_SERVER_PORT","50000")
],
];
+21
View File
@@ -0,0 +1,21 @@
<?php
/**
* This file is part of webman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
use Webman\Route;
+23
View File
@@ -0,0 +1,23 @@
<?php
/**
* This file is part of webman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
return [
'event_loop' => '',
'stop_timeout' => 2,
'pid_file' => runtime_path() . '/webman.pid',
'status_file' => runtime_path() . '/webman.status',
'stdout_file' => runtime_path() . '/logs/stdout.log',
'log_file' => runtime_path() . '/logs/workerman.log',
'max_package_size' => 10 * 1024 * 1024
];
+65
View File
@@ -0,0 +1,65 @@
<?php
/**
* This file is part of webman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
use Webman\Session\FileSessionHandler;
use Webman\Session\RedisSessionHandler;
use Webman\Session\RedisClusterSessionHandler;
return [
'type' => 'file', // or redis or redis_cluster
'handler' => FileSessionHandler::class,
'config' => [
'file' => [
'save_path' => runtime_path() . '/sessions',
],
'redis' => [
'host' => '127.0.0.1',
'port' => 6379,
'auth' => '',
'timeout' => 2,
'database' => '',
'prefix' => 'redis_session_',
],
'redis_cluster' => [
'host' => ['127.0.0.1:7000', '127.0.0.1:7001', '127.0.0.1:7001'],
'timeout' => 2,
'auth' => '',
'prefix' => 'redis_session_',
]
],
'session_name' => 'PHPSID',
'auto_update_timestamp' => false,
'lifetime' => 7*24*60*60,
'cookie_lifetime' => 365*24*60*60,
'cookie_path' => '/',
'domain' => '',
'http_only' => true,
'secure' => false,
'same_site' => '',
'gc_probability' => [1, 1000],
];
+23
View File
@@ -0,0 +1,23 @@
<?php
/**
* This file is part of webman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**
* Static file settings
*/
return [
'enable' => true,
'middleware' => [ // Static file Middleware
//app\middleware\StaticFile::class,
],
];
+25
View File
@@ -0,0 +1,25 @@
<?php
/**
* This file is part of webman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**
* Multilingual configuration
*/
return [
// Default language
'locale' => 'zh_CN',
// Fallback language
'fallback_locale' => ['zh_CN', 'en'],
// Folder where language files are stored
'path' => base_path() . '/resource/translations',
];
+22
View File
@@ -0,0 +1,22 @@
<?php
/**
* This file is part of webman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
use support\view\Raw;
use support\view\Twig;
use support\view\Blade;
use support\view\ThinkPHP;
return [
'handler' => Raw::class
];