listen
void Worker::listen(void)
Worker oluşturulduktan sonra dinleme işlemini gerçekleştirir.
Bu yöntem, Worker işlemi başlatıldıktan sonra dinamik olarak yeni Worker örnekleri oluşturmak için kullanılır; böylece aynı işlem içinde birden fazla port dinlenebilir ve çeşitli protokoller desteklenir. Bu yöntemin yalnızca mevcut işlemde dinleme eklemek için kullanılacağını ve yeni bir işlem oluşturmayacağını, ayrıca onWorkerStart yöntemini tetiklemez.
Örneğin, bir http Worker başlatıldığında bir websocket Worker örneği oluşturulursa, bu işlem hem http protokolü hem de websocket protokolü üzerinden erişilebilir. websocket Worker ve http Worker aynı işlem içinde bulunduğundan, ortak bellek değişkenlerine erişebilir ve tüm socket bağlantılarını paylaşabilir. Bu sayede http taleplerini alıp, websocket istemcisine veri gönderme işlemi benzeri bir işlem gerçekleştirilebilir.
Not:
Eğer PHP sürümü <=7.0 ise, aynı portta birden fazla alt işlemde Worker örnekleri oluşturulmasına izin verilmez. Örneğin, A işlemi 2016 portunu dinleyen bir Worker oluşturursa, B işlemi 2016 portunu dinleyen bir Worker daha oluşturamaz; aksi takdirde Address already in use hatası alır. Aşağıdaki kod çalışmaz.
use Workerman\Worker;
use Workerman\Connection\TcpConnection;
require_once __DIR__ . '/vendor/autoload.php';
$worker = new Worker();
// 4 işlem
$worker->count = 4;
// Her bir işlem başlatıldığında mevcut işlemde yeni bir Worker dinleme işlemi ekle
$worker->onWorkerStart = function($worker)
{
/**
* 4 işlem başlatıldığında hepsi 2016 portunu dinleyen Worker oluşturur
* worker->listen() çağrıldığında Address already in use hatası verir
* Eğer worker->count=1 olursa hata vermez
*/
$inner_worker = new Worker('http://0.0.0.0:2016');
$inner_worker->onMessage = 'on_message';
// Dinlemeyi gerçekleştir. Burada Address already in use hatası verir
$inner_worker->listen();
};
$worker->onMessage = 'on_message';
function on_message(TcpConnection $connection, $data)
{
$connection->send("hello\n");
}
// worker'ı çalıştır
Worker::runAll();
Eğer PHP sürümünüz >=7.0 ise, Worker->reusePort=true ayarı yapabilirsiniz; böylece birden fazla alt işlem aynı portta Worker oluşturabilir. Aşağıdaki örneğe bakınız:
use Workerman\Worker;
use Workerman\Connection\TcpConnection;
require_once __DIR__ . '/vendor/autoload.php';
$worker = new Worker('text://0.0.0.0:2015');
// 4 işlem
$worker->count = 4;
// Her bir işlem başlatıldığında mevcut işlemde yeni bir Worker dinleme işlemi ekle
$worker->onWorkerStart = function($worker)
{
$inner_worker = new Worker('http://0.0.0.0:2016');
// Port yeniden kullanımını ayarlama, aynı portta dinleyen Worker oluşturulmasına izin verir (PHP>=7.0 gerektirir)
$inner_worker->reusePort = true;
$inner_worker->onMessage = 'on_message';
// Dinlemeyi gerçekleştir. Normal dinleme hatası vermez
$inner_worker->listen();
};
$worker->onMessage = 'on_message';
function on_message(TcpConnection $connection, $data)
{
$connection->send("hello\n");
}
// worker'ı çalıştır
Worker::runAll();
Örnek PHP arka uç ile istemciye anlık mesaj iletimi
Prensip:
-
Bir websocket Worker oluşturun, istemci uzun bağlantısını sürdürmek için
-
websocket Worker içerisinde bir text Worker oluşturun
-
websocket Worker ile text Worker aynı işlem içindedir, bu nedenle istemci bağlantısını paylaşmak kolaydır
-
Bir bağımsız PHP arka uç sistemi, text protokolü aracılığıyla text Worker ile iletişim kurar
-
text Worker, websocket bağlantısını kullanarak veri iletimini gerçekleştirir
Kod ve adımlar
push.php
<?php
use Workerman\Worker;
use Workerman\Connection\TcpConnection;
require_once __DIR__ . '/vendor/autoload.php';
// 1234 portunu dinleyen bir worker konteyneri başlat
$worker = new Worker('websocket://0.0.0.0:1234');
/*
* Burada işlem sayısı 1 olarak ayarlanmış olmalıdır
*/
$worker->count = 1;
// worker işlemi başlatıldığında, dahili bir iletişim portu açmak için bir text Worker oluşturun
$worker->onWorkerStart = function($worker)
{
// Dahili bir port açın, böylece iç sistem veri iletmeye kolayca ulaşabilir, Text protokolü formatında metin + yeni satır karakteri
$inner_text_worker = new Worker('text://0.0.0.0:5678');
$inner_text_worker->onMessage = function(TcpConnection $connection, $buffer)
{
// $data dizisi formatı; içinde uid bulunur ve bu belirli bir uid sayfasına veri iletilir
$data = json_decode($buffer, true);
$uid = $data['uid'];
// workerman aracılığıyla uid sayfasına veri ilet
$ret = sendMessageByUid($uid, $buffer);
// İletim sonucunu geri döndür
$connection->send($ret ? 'ok' : 'fail');
};
// ## Dinlemeyi gerçekleştir ##
$inner_text_worker->listen();
};
// uid ile bağlantı arasında haritalamak için yeni bir özellik ekle
$worker->uidConnections = array();
// Herhangi bir istemciden mesaj geldiğinde çağrılan geri çağırma işlevi
$worker->onMessage = function(TcpConnection $connection, $data)
{
global $worker;
// Mevcut istemcinin doğrulanıp doğrulanmadığını, yani uid'nin ayarlanıp ayarlanmadığını kontrol edin
if(!isset($connection->uid))
{
// Doğrulanmadıysa, ilk paketi uid olarak alın (burada kolaylık olması açısından gerçek bir doğrulama yapılmamıştır)
$connection->uid = $data;
/* uid ile bağlantı arasında haritayı kaydedin, böylece uid üzerinden bağlantıyı kolayca bulabilirsiniz,
* belirli bir uid'ye veri iletimi için
*/
$worker->uidConnections[$connection->uid] = $connection;
return;
}
};
// Bir istemci bağlantısı kapandığında
$worker->onClose = function(TcpConnection $connection)
{
global $worker;
if(isset($connection->uid))
{
// Bağlantı kapandığında haritayı kaldır
unset($worker->uidConnections[$connection->uid]);
}
};
// Tüm doğrulanan kullanıcılara veri iletimi
function broadcast($message)
{
global $worker;
foreach($worker->uidConnections as $connection)
{
$connection->send($message);
}
}
// uid'ye veri iletimi
function sendMessageByUid($uid, $message)
{
global $worker;
if(isset($worker->uidConnections[$uid]))
{
$connection = $worker->uidConnections[$uid];
$connection->send($message);
return true;
}
return false;
}
// Tüm worker'ları çalıştır
Worker::runAll();
Arka uç hizmetini başlat
php push.php start -d
İstemcinin iletileri alması için JS kodu
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);
};
Arka uç mesaj iletimi kodu
// Dahili iletim portuna socket bağlantısı kur
$client = stream_socket_client('tcp://127.0.0.1:5678', $errno, $errmsg, 1);
// İletilen veri, uid alanını içerir, bu uid'ye iletilen veridir
$data = array('uid'=>'uid1', 'percent'=>'88%');
// Veri iletimi, 5678 portunun Text protokolü olduğunu unutmayın, Text protokolü, verinin sonuna yeni satır karakteri eklemeyi gerektirir
fwrite($client, json_encode($data)."\n");
// İletim sonucunu oku
echo fread($client, 8192);