🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] ## **支持监听的格式** ``` <?php require_once __DIR__ . '/vendor/autoload.php'; use Workerman\Connection\TcpConnection; use Workerman\Worker; $version=Worker::VERSION; $starting_status=Worker::STATUS_STARTING; $runing_status=Worker::STATUS_RUNNING; $shutdown_status=Worker::STATUS_SHUTDOWN; $reloading_status=Worker::STATUS_RELOADING; $default_backlog=Worker::DEFAULT_BACKLOG; $max_udp_package_size=Worker::MAX_UDP_PACKAGE_SIZE; $ui_safe_length=Worker::UI_SAFE_LENGTH; #Worker::__construct([string $listen , array $context]) #$listen 的格式为 <协议>://<监听地址> #<监听地址> 可以为以下格式: #unix套接字,地址为本地一个磁盘路径 #非unix套接字,地址格式为 <本机ip>:<端口号> #tcp: 例如 tcp://0.0.0.0:8686 #udp: 例如 udp://0.0.0.0:8686 #unix: 例如 unix:///tmp/my_file (需要Workerman>=3.2.7) #http: 例如 http://0.0.0.0:80 #websocket: 例如 websocket://0.0.0.0:8686 #text: 例如 text://0.0.0.0:8686 (text是Workerman内置的文本协议,兼容telnet,详情参见附录Text协议部分) #<本机ip>如果以为0.0.0.0表示监听本机所有网卡,包括内网ip和外网ip及本地回环127.0.0.1 #<本机ip>如果以为127.0.0.1表示监听本地回环,只能本机访问,外部无法访问 #<本机ip>如果为内网ip,类似192.168.xx.xx,表示只监听内网ip,则外网用户无法访问 #注意:<端口号>不能大于65535。<端口号>如果小于1024则需要root权限才能监听。监听的端口必须是本机未被占用的端口,否则无法监听,并且提示Address already in use错误 $ws = new Worker('websocket://0.0.0.0:8181'); $ws->count=2;#启动2个进程 $ws->onConnect = function($connection){ $connection->onWebSocketConnect = function($connection , $httpBuffer) { echo "本次链接的客户端IP:".$connection->getRemoteIp().PHP_EOL; var_dump($_GET, $_SERVER); // 可以在这里判断连接来源是否合法,不合法就关掉连接 // $_SERVER['HTTP_ORIGIN']标识来自哪个站点的页面发起的websocket连接 if($_SERVER['HTTP_ORIGIN'] != 'https://www.workerman.net') { // $connection->close(); return $_SERVER['HTTP_ORIGIN']; } // onWebSocketConnect 里面$_GET $_SERVER是可用的 // var_dump($_GET, $_SERVER); }; }; $ws->onMessage = function($connection,$data){ $connection->send("我已收到你发来的数据:".$data); }; Worker::runAll(); ``` >[info][PHP几种回调写法](https://www.workerman.net/doc/workerman/faq/callback_methods.html) ## **构造函数为空时可以作为定时任务** ``` use \Workerman\Worker; use \Workerman\Timer; require_once __DIR__ . '/vendor/autoload.php'; $task = new Worker(); $task->onWorkerStart = function($task) { // 每2.5秒执行一次 $time_interval = 2.5; Timer::add($time_interval, function() { echo "task run\n"; }); }; // 运行worker Worker::runAll(); ``` ## **定时向客户端的用户们发送消息** ~~~php use Workerman\Worker; use Workerman\Timer; require_once __DIR__ . '/vendor/autoload.php'; $worker = new Worker('text://0.0.0.0:2020'); // 进程启动时设置一个定时器,定时向所有客户端连接发送数据 $worker->onWorkerStart = function($worker) { // 定时,每10秒一次 Timer::add(10, function()use($worker) { // 遍历当前进程所有的客户端连接,发送当前服务器的时间 foreach($worker->connections as $connection) { $connection->send(time()); } }); }; // 运行worker Worker::runAll(); ~~~ ## **Worker监听自定义协议的端口** [Worker监听自定义协议的端口](https://www.workerman.net/doc/workerman/worker/construct.html) 最终的目录结构 ~~~ ├── Protocols // 这是要创建的Protocols目录 │   └── MyTextProtocol.php // 这是要创建的自定义协议文件 ├── test.php // 这是要创建的test脚本 └── Workerman // Workerman源码目录,里面代码不要动 ~~~ 1、创建Protocols目录,并创建一个协议文件 Protocols/MyTextProtocol.php(参照上面目录结构) ~~~php // 用户自定义协议命名空间统一为Protocols namespace Protocols; //简单文本协议,协议格式为 文本+换行 class MyTextProtocol { // 分包功能,返回当前包的长度 public static function input($recv_buffer) { // 查找换行符 $pos = strpos($recv_buffer, "\n"); // 没找到换行符,表示不是一个完整的包,返回0继续等待数据 if($pos === false) { return 0; } // 查找到换行符,返回当前包的长度,包括换行符 return $pos+1; } // 收到一个完整的包后通过decode自动解码,这里只是把换行符trim掉 public static function decode($recv_buffer) { return trim($recv_buffer); } // 给客户端send数据前会自动通过encode编码,然后再发送给客户端,这里加了换行 public static function encode($data) { return $data."\n"; } } ~~~ 2、使用MyTextProtocol协议监听处理请求 参照上面最终目录结构创建test.php文件 ~~~php use Workerman\Worker; use Workerman\Connection\TcpConnection; require_once __DIR__ . '/vendor/autoload.php'; // #### MyTextProtocol worker #### $text_worker = new Worker("MyTextProtocol://0.0.0.0:5678"); /* * 收到一个完整的数据(结尾是换行)后,自动执行MyTextProtocol::decode('收到的数据') * 结果通过$data传递给onMessage回调 */ $text_worker->onMessage = function(TcpConnection $connection, $data) { var_dump($data); /* * 给客户端发送数据,会自动调用MyTextProtocol::encode('hello world')进行协议编码, * 然后再发送到客户端 */ $connection->send("hello world"); }; // run all workers Worker::runAll(); ~~~ 3、测试 打开终端,进入到test.php所在目录,执行`php test.php start` ~~~ php test.php start Workerman[test.php] start in DEBUG mode ----------------------- WORKERMAN ----------------------------- Workerman version:3.2.7 PHP version:5.4.37 ------------------------ WORKERS ------------------------------- user worker listen processes status root none myTextProtocol://0.0.0.0:5678 1 [OK] ---------------------------------------------------------------- Press Ctrl-C to quit. Start success. ~~~ 打开终端,利用telnet测试(建议用linux系统的telnet) 假设是本机测试, 终端执行 telnet 127.0.0.1 5678 然后输入 hi回车 会接收到数据hello world\\n ~~~ telnet 127.0.0.1 5678 Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. hi hello world ~~~