예제 1
(요구사항: Workerman 버전 >= 3.3.0)
Worker 기반의 다중 프로세스 그룹 푸시 시스템
use Workerman\Worker;
use Workerman\Connection\TcpConnection;
require_once __DIR__ . '/vendor/autoload.php';
$channel_server = new Channel\Server('0.0.0.0', 2206);
$worker = new Worker('websocket://0.0.0.0:1234');
$worker->count = 8;
// 전체 그룹과 연결의 매핑 배열
$group_con_map = array();
$worker->onWorkerStart = function(){
// Channel 클라이언트가 Channel 서버에 연결
Channel\Client::connect('127.0.0.1', 2206);
// 전체 그룹 메시지 전송 이벤트를 청취
Channel\Client::on('send_to_group', function($event_data){
$group_id = $event_data['group_id'];
$message = $event_data['message'];
global $group_con_map;
var_dump(array_keys($group_con_map));
if (isset($group_con_map[$group_id])) {
foreach ($group_con_map[$group_id] as $con) {
$con->send($message);
}
}
});
};
$worker->onMessage = function(TcpConnection $con, $data){
// 그룹 가입 메시지 {"cmd":"add_group", "group_id":"123"}
// 또는 그룹 메시지 보내기 {"cmd":"send_to_group", "group_id":"123", "message":"이것은 메시지입니다"}
$data = json_decode($data, true);
var_dump($data);
$cmd = $data['cmd'];
$group_id = $data['group_id'];
switch($cmd) {
// 연결이 그룹에 가입됨
case "add_group":
global $group_con_map;
// 연결을 해당 그룹 배열에 추가
$group_con_map[$group_id][$con->id] = $con;
// 이 연결이 가입한 그룹을 기록, onclose 시에 group_con_map의 해당 그룹 데이터를 정리하는 데 유용
$con->group_id = isset($con->group_id) ? $con->group_id : array();
$con->group_id[$group_id] = $group_id;
break;
// 그룹에 메시지 보내기
case "send_to_group":
// Channel\Client가 모든 서버의 모든 프로세스에 그룹 메시지 전송 이벤트 방송
Channel\Client::publish('send_to_group', array(
'group_id'=>$group_id,
'message'=>$data['message']
));
break;
}
};
// 여기서 매우 중요, 연결이 닫힐 때 연결을 전체 그룹 데이터에서 제거하여 메모리 누수를 방지
$worker->onClose = function(TcpConnection $con){
global $group_con_map;
// 연결이 가입한 모든 그룹을 순회하며, group_con_map에서 해당 데이터를 삭제
if (isset($con->group_id)) {
foreach ($con->group_id as $group_id) {
unset($group_con_map[$group_id][$con->id]);
if (empty($group_con_map[$group_id])) {
unset($group_con_map[$group_id]);
}
}
}
};
Worker::runAll();
테스트 (모두 127.0.0.1에서 실행한다고 가정)
- 서버 실행
php start.php start Workerman[del.php] DEBUG 모드에서 시작 ----------------------- WORKERMAN ----------------------------- Workerman 버전:3.4.2 PHP 버전:7.1.3 ------------------------ WORKERS ------------------------------- 사용자 작업자 리스닝 프로세스 상태 liliang ChannelServer frame://0.0.0.0:2206 1 [OK] liliang none websocket://0.0.0.0:1234 12 [OK] ---------------------------------------------------------------- 종료하려면 Ctrl-C를 누르세요. 시작 성공.
2. 클라이언트가 서버에 연결
크롬 브라우저를 열고 F12를 눌러 개발자 콘솔을 열고, Console 탭에 입력(또는 아래 코드를 HTML 페이지에 넣어 JS로 실행)
```javascript
// 서버 IP가 127.0.0.1이라고 가정, 테스트 시 실제 서버 IP로 변경하세요
ws = new WebSocket('ws://127.0.0.1:1234');
ws.onmessage = function(data){console.log(data.data)};
ws.onopen = function() {
ws.send('{"cmd":"add_group", "group_id":"123"}');
ws.send('{"cmd":"send_to_group", "group_id":"123", "message":"이것은 메시지입니다"}');
};