合规国际互联网加速 OSASE为企业客户提供高速稳定SD-WAN国际加速解决方案。 广告
# [Worker类](https://www.workerman.net/doc/workerman/worker.html#Worker%E7%B1%BB) Workerman中有两个重要的类Worker与Connection。 Worker类用于实现端口的监听,并可以设置客户端连接事件、连接上消息事件、连接断开事件的回调函数,从而实现业务处理。 可以设置Worker实例的进程数(count属性),Worker主进程会fork出count个子进程同时监听相同的端口,并行的接收客户端连接,处理连接上的事件。 ``` <?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; // 所有的打印输出全部保存在/tmp/stdout.log文件中,默认所有终端输出全部重定向到/dev/null (也就是默认丢弃所有输出) #Worker::$stdoutFile = '/tmp/stdout.log'; #此属性为全局静态属性,用来设置Workerman进程的pid文件路径此项设置在监控中比较有用,例如将Workerman的pid文件放入固定的目录中,可以方便一些监控软件读取pid文件,从而监控Workerman进程状态。注意:此属性必须在Worker::runAll();运行前设置才有效。windows系统不支持此特性。 #如果不设置,Workerman默认会在与Workerman目录平行的位置(注意workerman3.2.3之前版本默认在sys_get_temp_dir()下)自动生成一个pid文件,并且为了避免启动多个Workerman实例导致pid冲突,Workerman生成pid文件包含了当前Workerman的路径 #Worker::$pidFile = '/var/run/workerman.pid'; #用来指定workerman日志文件位置,仅仅记录workerman自身相关启动停止等日志,不包含任何业务日志。业务日志类可以利用file_put_contents 或者 error_log 等函数自行实现 #Worker::$logFile = '/tmp/workerman.log'; #此属性为全局静态属性,表示是否以daemon(守护进程)方式运行。如果启动命令使用了 -d参数,则该属性会自动设置为true。也可以代码中手动设置.此属性必须在Worker::runAll();运行前设置才有效。windows系统不支持此特性 Worker::$daemonize = true; #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错误 $worker = new Worker('websocket://0.0.0.0:8181'); #设置当前Worker实例的协议类。他会将上面实例化时设置的的websocket协议替换为http #$worker->protocol = 'Workerman\\Protocols\\Http'; #设置当前Worker实例所使用的传输层协议,目前只支持3种(tcp、udp、ssl)。不设置默认为tcp #$worker->transport = 'udp'; #设置当前Worker实例以哪个用户运行。此属性只有当前用户为root时才能生效。不设置时默认以当前用户运行 #建议$user设置权限较低的用户,例如www-data、apache、nobody等.此属性必须在Worker::runAll();运行前设置才有效。windows系统不支持此特性 #$worker->user = 'www-data'; $worker->count=4;#启动4个进程 // 设置当前Worker实例的名称,方便运行status命令时识别进程。不设置时默认为none。 $worker->name = 'MyWebsocketWorker'; #php a.php restart #---------------------------------------------- WORKERMAN ---------------------------------------------- #Workerman version:4.1.15 PHP version:8.2.16 Event-Loop:\Workerman\Events\Event #----------------------------------------------- WORKERS ----------------------------------------------- #proto user worker listen processes status #tcp root MyWebsocketWorker websocket://0.0.0.0:8181 4 [OK] #------------------------------------------------------------------------------------------------------- #一般更新业务代码时使用.执行php start.php reload时会向所有子进程发送reload信号(SIGUSR1),子进程收到reload信号后会自动退出然后主进程会自动拉起一个新的进程 #收到reload信号后只想让子进程执行onWorkerReload,不想退出时设置reloadable为false $worker->reloadable = false; #当客户端与Workerman建立连接时(TCP三次握手完成后)触发的回调函数。每个连接只会触发一次onConnect回调. #在onConnect事件里无法确认对方是谁。要想知道对方是谁,需要客户端发送鉴权数据,例如某个token或者用户名密码之类,在onMessage回调里做鉴权. #udp是无连接的,所以当使用udp协议时不会触发onConnect回调,也不会触发onClose回调 $worker->onConnect = function($connection){ echo "connection的id".$connection->id."\n"; $connection->onWebSocketConnect = function($connection , $httpBuffer) { echo "本次链接的客户端IP:".$connection->getRemoteIp().PHP_EOL; var_dump($_GET, $_SERVER); /* $_SERVER array ( 'REQUEST_METHOD' => 'GET', 'REQUEST_URI' => '/', 'SERVER_PROTOCOL' => 'HTTP/1.1', 'HTTP_HOST' => '102.10.80.185:8181', 'SERVER_NAME' => '102.10.80.185', 'SERVER_PORT' => '8181', 'HTTP_CONNECTION' => 'Upgrade', 'HTTP_PRAGMA' => 'no-cache', 'HTTP_CACHE_CONTROL' => 'no-cache', 'HTTP_USER_AGENT' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36 Edg/127.0.0.0', 'HTTP_UPGRADE' => 'websocket', 'HTTP_ORIGIN' => 'http://102.10.80.185', 'HTTP_SEC_WEBSOCKET_VERSION' => '13', 'HTTP_ACCEPT_ENCODING' => 'gzip, deflate', 'HTTP_ACCEPT_LANGUAGE' => 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6', 'HTTP_COOKIE' => '字符太多省略', 'HTTP_SEC_WEBSOCKET_KEY' => 'oVzl7peN3SAMcTRqnL/USw==', 'HTTP_SEC_WEBSOCKET_EXTENSIONS' => 'permessage-deflate; client_max_window_bits', 'QUERY_STRING' => '', ) */ var_export($_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); }; }; #设置Worker子进程启动时的回调函数,每个子进程启动时都会执行 #注意:onWorkerStart是在子进程启动时运行的,如果开启了多个子进程($worker->count > 1),每个子进程运行一次,则总共会运行$worker->count次 $worker->onWorkerStart = function($worker){ #当前worker进程的id编号,范围为0到$worker->count-1 echo "进程id:{$worker->id} Worker starting...\n"; }; #Worker收到reload信号后执行的回调 #子进程收到reload信号默认的动作是退出重启,以便新进程重新加载业务代码完成代码更新。所以reload后子进程在执行完onWorkerReload回调后便立刻退出是正常现象.如果在收到reload信号后只想让子进程执行onWorkerReload,不想退出,可以在初始化Worker实例时设置对应的Worker实例的reloadable属性为false `$worker->reloadable = false;` $worker->onWorkerReload = function($worker){ #此属性中存储了当前进程的所有的客户端连接对象,其中id为connection的id编号 foreach($worker->connections as $connectionId => $connection) { $connection->send('worker reloading'); } }; #当客户端通过连接发来数据时(Workerman收到数据时)触发的回调函数 $worker->onMessage = function($connection,$data){ $connection->send("我已收到你发来的数据:".$data); }; #当客户端连接与Workerman断开时触发的回调函数 #注意:如果对端是由于断网或者断电等极端情况断开的连接,这时由于无法及时发送tcp的fin包给workerman,workerman就无法得知连接已经断开,也就无法及时触发onClose。这种情况需要通过应用层心跳来解决。workerman中连接的心跳实现参见这里。如果使用的是GatewayWorker框架,则直接使用GatewayWorker框架的心跳机制即可,参见https://doc2.workerman.net/heartbeat.html。 $worker->onClose = function(TcpConnection $connection) { echo "connection closed\n"; }; #应用层发送缓冲区满则会触发onBufferFull回调 $worker->onBufferFull = function(TcpConnection $connection) { echo "bufferFull and do not send again\n"; }; #在应用层发送缓冲区数据全部发送完毕后触发。一般与onBufferFull配合使用,例如在onBufferFull时停止向对端继续send数据,在onBufferDrain恢复写入数据 $worker->onBufferDrain = function(TcpConnection $connection) { echo "buffer drain and continue send\n"; }; #当客户端的连接上发生错误时触发 $worker->onError = function(TcpConnection $connection, $code, $msg) { echo "error $code $msg\n"; }; Worker::runAll(); ```