개발 과정에서 우리는 종종 다음과 같은 상황에 직면하게 됩니다. 프런트엔드 목록에는 백엔드 데이터베이스의 데이터가 표시되지만, 백엔드의 특정 인터페이스에서 데이터베이스에 데이터 조각이 삽입되면 데이터베이스가 업데이트되었지만 프런트엔드 디스플레이 데이터가 표시되지 않습니다. 업데이트되지 않았으므로 수동으로 새로 고쳐야 합니다. 하지만 매번 수동으로 업데이트하는 것은 너무 번거롭습니다. 이때 Workerman을 사용하여 문제를 해결할 수 있습니다.
Workerman Framework는 순수하게 PHP로만 개발된 오픈 소스 고성능 PHP 소켓 서버 프레임워크입니다. 모바일 앱, 모바일 통신, WeChat 애플릿, 모바일 게임 서버, 온라인 게임, PHP 채팅방, 하드웨어 통신, 스마트 홈, 차량 인터넷, 사물 인터넷 및 기타 분야의 개발에 널리 사용됩니다. TCP 긴 연결을 지원하고 Websocket, HTTP 및 기타 프로토콜을 지원하며 사용자 정의 프로토콜을 지원합니다. 비동기 Mysql, 비동기 Redis, 비동기 Http, 비동기 메시지 대기열 등과 같은 많은 고성능 구성 요소가 있습니다.
그러면 위의 문제를 해결하려면 어떻게 사용해야 할까요?
1. 메시지를 서로 푸시하기 위해 긴 웹소켓 연결을 설정합니다.
2. 백엔드 내부에 수신 프로세스가 설정됩니다(프로토콜 제한 없음).
3. 내부 수신 포트로 데이터를 푸시하려고 합니다
4. 내부 수신 포트에서 푸시 메시지를 받은 후 백엔드는 웹소켓을 통해 메시지를 프런트엔드로 푸시하여 새로 고침을 수행합니다
소스 코드를 다운로드한 후 Workerman 프레임워크에서 위 프로세스를 구현해 보겠습니다.
구현 코드:
server.php
<?php use Workerman\Worker; require_once __DIR__ . '/../../vendor/autoload.php'; // 初始化一个worker容器,监听1234端口 $worker = new Worker('websocket://0.0.0.0:1234');// /* * 注意这里进程数必须设置为1,否则会报端口占用错误 * (php 7可以设置进程数大于1,前提是$inner_text_worker->reusePort=true) */ $worker->count = 1; // worker进程启动后创建一个text Worker以便打开一个内部通讯端口 $worker->onWorkerStart = function($worker) { // 开启一个内部端口,方便内部系统推送数据,Text协议格式 文本+换行符 $inner_text_worker = new Worker('text://0.0.0.0:5678'); $inner_text_worker->onMessage = function($connection, $buffer) { // $data数组格式,里面有uid,表示向那个uid的页面推送数据 $data = json_decode($buffer, true); $uid = $data['uid']; // 通过workerman,向uid的页面推送数据 $ret = sendMessageByUid($uid, $buffer); // 返回推送结果 $connection->send($ret ? 'ok' : 'fail'); }; // ## 执行监听 ## $inner_text_worker->listen(); }; // 新增加一个属性,用来保存uid到connection的映射 $worker->uidConnections = array(); // 当有客户端发来消息时执行的回调函数 $worker->onMessage = function($connection, $data) { global $worker; // 判断当前客户端是否已经验证,既是否设置了uid if(!isset($connection->uid)) { // 没验证的话把第一个包当做uid(这里为了方便演示,没做真正的验证) $connection->uid = $data; /* 保存uid到connection的映射,这样可以方便的通过uid查找connection, * 实现针对特定uid推送数据 */ $worker->uidConnections[$connection->uid] = $connection; return; } }; // 当有客户端连接断开时 $worker->onClose = function($connection) { global $worker; if(isset($connection->uid)) { // 连接断开时删除映射 unset($worker->uidConnections[$connection->uid]); } }; // 向所有验证的用户推送数据 function broadcast($message) { global $worker; foreach($worker->uidConnections as $connection) { $connection->send($message); } } // 针对uid推送数据 function sendMessageByUid($uid, $message) { global $worker; if(isset($worker->uidConnections[$uid])) { $connection = $worker->uidConnections[$uid]; $connection->send($message); return true; } return false; } // 运行所有的worker Worker::runAll();
push.php
<?php //插入数据库操作 // 建立socket连接到内部推送端口 $client = stream_socket_client('tcp://127.0.0.1:5678', $errno, $errmsg, 1); // 推送的数据,包含uid字段,表示是给这个uid推送 $data = array('uid'=>'uid1', 'percent'=>'88%'); // 发送数据,注意5678端口是Text协议的端口,Text协议需要在数据末尾加上换行符 fwrite($client, json_encode($data)."\n"); // 读取推送结果 echo fread($client, 8192); ?>
clien.html
<!DOCTYPE html> <html> <head> <title></title> </head> <body> <script> var ws = new WebSocket('ws://127.0.0.1:1234'); ws.onopen = function(){ var uid = 'uid1'; ws.send(uid); }; ws.onmessage = function(e){ //alert(e.data); console.log(e.data); //window.location.reload(); }; </script> </body> </html>
실행 프로세스:
cmd 열기, server.php 실행
프런트 엔드 페이지 및 콘솔 열기
cmd를 열고 push.php를 실행하세요
이때 프론트엔드 페이지를 보는 동안 콘솔에 메시지가 수신됩니다.
더 많은 워커맨 지식을 알고 싶으시면 PHP 중국어 웹사이트의 workerman tutorial 칼럼을 주목해주세요.
위 내용은 백엔드 메시지를 Workerman의 프런트엔드로 실시간으로 푸시하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!