| 模式 | 連接發起方 | 實現要點 |
| PORT (主動) | 服務器連接客戶端 IP:PORT | 需服務器有公網 IP、客戶端無防火牆 |
| PASV (被動) | 客戶端連接服務器 IP:PORT | 需開放被動端口範圍、NAT 環境需配置外網 IP |
Swoole 實現:數據通道同樣使用 Swoole\Server TCP 監聽,或協程 Swoole\Coroutine\Socket 主動連接。
3. 異步文件 IO:大文件傳輸不阻塞 Worker
- Swoole
Swoole\Async::readFile / writeFile / read / write
- 或使用協程
Swoole\Coroutine\File::open + read/write
- 傳輸流水線:網絡讀 → 文件寫(上傳) / 文件讀 → 網絡寫(下載),緩衝區控制背壓
4. SSL/TLS 加密:FTPS 實現
- Swoole
Swoole\Server::set(['ssl_cert_file' => ..., 'ssl_key_file' => ...])
- 支持顯式 FTPS (Explicit):命令通道啟動後 `AUTH TLS` 升級加密
- 需處理數據通道加密:`PROT P` 私密模式
- 證書建議使用 Let's Encrypt 通配符證書,配置自動續期腳本
5. 進程間共享狀態:在線用戶、限流、配額
Swoole\Table:高性能共享內存表,存儲在線會話、IP 連接數、傳輸統計
Swoole\Atomic / Swoole\Lock:計數器、分佈式鎖
- Worker 進程間通過 Table 實現「單用戶單點登錄」、「全局帶寬限制」
6. 內置 Web 管理:Swoole\Http\Server
- 同一進程或獨立進程啟動 HTTP 服務
- RESTful API:
GET /api/users、POST /api/users、GET /api/sessions、DELETE /api/sessions/{id}
- 前端:Vue 3 + Element Plus / AdminLTE,WebSocket 推送實時日誌/流量圖表
- 認證:JWT 或 Session + CSRF
配置文件示例 conf/config.php
[
'host' => '0.0.0.0',
'port' => 21,
'passive_port_range' => [50000, 50100], // 被動模式端口池
'passive_ip' => 'auto', // auto / 具體公網 IP
'ssl' => [
'enabled' => true,
'cert_file' => __DIR__ . '/ssl.crt',
'key_file' => __DIR__ . '/ssl.key',
'verify_peer' => false,
],
'max_connections' => 1000,
'max_connections_per_ip' => 10,
'idle_timeout' => 300, // 秒
'transfer_buffer_size' => 8192,
'banner' => 'Welcome to Custom PHP FTP Server',
],
'user' => [
'storage_driver' => 'file', // file / redis / mysql
'storage_path' => __DIR__ . '/../data/users.php',
'default_quota' => 1024 * 1024 * 1024, // 1GB
'password_min_length' => 8,
'password_require_mixed' => true,
],
'web' => [
'host' => '0.0.0.0',
'port' => 8080,
'jwt_secret' => 'your_jwt_secret_key',
'jwt_ttl' => 3600,
],
'log' => [
'path' => __DIR__ . '/../logs',
'level' => 'info',
'max_files' => 30,
],
'smtp' => [
'host' => 'smtp.exmail.qq.com',
'port' => 465,
'username' => 'ftp-admin@yourdomain.com',
'password' => 'your_password',
'from' => 'FTP Server ',
'encryption' => 'ssl',
],
];
入口文件 MyFtpServer.php
['size' => 10000, 'cols' => ['fd' => 'int', 'user' => 'string', 'ip' => 'string', 'login_time' => 'int', 'bytes_up' => 'int', 'bytes_down' => 'int', 'status' => 'string']],
'ip_stats' => ['size' => 50000, 'cols' => ['count' => 'int', 'last_seen' => 'int']],
'global' => ['size' => 100, 'cols' => ['total_users' => 'int', 'total_transfer' => 'float']],
]);
// 用戶管理器
$userManager = new User($config['user'], $shared);
// FTP 服務器
$ftpServer = new CFtpServer($config['ftp'], $userManager, $shared);
// Web 管理服務器
$webServer = new CWebServer($config['web'], $userManager, $shared);
// 信號處理
function shutdown($ftp, $web) {
return function ($signo) use ($ftp, $web) {
echo "Signal $signo received, shutting down...\n";
$ftp->stop();
$web->stop();
exit(0);
};
}
pcntl_signal(SIGTERM, shutdown($ftpServer, $webServer));
pcntl_signal(SIGINT, shutdown($ftpServer, $webServer));
pcntl_signal(SIGUSR1, function () use ($ftpServer, $webServer) {
// 平滑重啟 Worker
$ftpServer->reload();
$webServer->reload();
});
// 啟動(阻塞)
// 注意:Swoole\Server::start() 會 fork 多進程,主進程阻塞在這裡
// FTP 和 Web 可以分別在不同進程組運行,這裡簡化為順序啟動演示
// 實際生產建議用 Swoole\Process 管理多個 Server 實例
$ftpServer->start(); // 這裡會阻塞,Web Server 需在另一進程啟動
// 實際架構見下文說明
進程架構說明
主進程 (Master Process)
├── Manager Process (FTP)
│ ├── Worker Process 1 (FTP) -- 處理命令通道、數據傳輸
│ ├── Worker Process 2 (FTP)
│ └── ... (根據 cpu 核心數)
├── Manager Process (Web)
│ ├── Worker Process 1 (HTTP) -- 處理管理 API、靜態資源
│ └── Worker Process 2 (HTTP)
└── Task Worker Processes (可選) -- 異步任務:日誌寫入、郵件發送、配額統計
實際部署時,FTP 和 Web 可作為兩個獨立的 Swoole\Server 實例,通過 Swoole\Process 管理,共享同一 ShareMemory 實例(基於文件映射或 SysV 共享內存)。
下一步預告
系列第二部分將深入實現:
CFtpServer.php 核心協議處理:命令解析器、狀態機、認證流程
User.php 用戶權限體系:虛擬用戶存儲、路徑權限匹配、配額檢查
- 被動模式端口池管理、數據通道建立邏輯
- FTPS 顯式加密握手流程
總結
基於 PHP Swoole 自研 FTP 服務器,核心優勢在於業務邏輯深度融合(用戶系統、權限模型、配額統計直接復用項目代碼)、協議層面完全可控(支持自定義命令、混合協議)、運維友好(統一部署、熱重載、Web 可視化管理)。本文確立了項目架構、目錄結構、配置體系、進程模型,為後續核心代碼實現奠定基礎。
- 上一篇文章: PHP 人民幣數值轉中文大寫封裝類:支持進位、零處理、繁簡體、多幣種單位的企業級實現
- 下一篇文章: PHP 實現抽獎概率算法:大轉盤、刮刮卡等場景的完整解決方案
Copyright ©
程式碼之家 All Rights Reserved