सुनें

void Worker::listen(void)

Worker को इंस्टैंशिएट करने के बाद सुनने के लिए प्रयोग किया जाता है।

यह विधि मुख्य रूप से Worker प्रक्रिया को शुरू करने के बाद गतिशील रूप से नए Worker इंस्टैंस बनाने के लिए उपयोग की जाती है, जो एक ही प्रक्रिया में कई पोर्ट सुनने की अनुमति देती है और विभिन्न प्रोटोकॉल का समर्थन करती है। ध्यान देने योग्य बात यह है कि इस विधि का उपयोग केवल वर्तमान प्रक्रिया में सुनने को जोड़ने के लिए किया जाता है, नए प्रक्रियाओं को गतिशील रूप से बनाने के लिए नहीं, और यह onWorkerStart विधि को भी सक्रिय नहीं करता है।

उदाहरण के लिए, यदि एक http Worker शुरू करने के बाद एक websocket Worker इंस्टैंशिएट किया जाता है, तो यह प्रक्रिया http प्रोटोकॉल के माध्यम से और websocket प्रोटोकॉल के माध्यम से भी पहुंच सकेंगी। चूंकि websocket Worker और http Worker एक ही प्रक्रिया में हैं, इसलिए वे साझा मेमोरी वेरिएबल्स तक पहुंच सकते हैं और सभी socket कनेक्शनों को साझा कर सकते हैं। इसका मतलब है कि http अनुरोध को प्राप्त करके websocket क्लाइंट के लिए डेटा धकेलने के समान प्रभाव प्राप्त किया जा सकता है।

ध्यान दें:

यदि PHP संस्करण <= 7.0 है, तो समान पोर्ट के Worker को कई उप-प्रक्रियाओं में इंस्टैंशिएट करने का समर्थन नहीं है। उदाहरण के लिए, यदि प्रक्रिया A ने 2016 पोर्ट के लिए Worker बनाया है, तो प्रक्रिया B फिर से 2016 पोर्ट के लिए Worker नहीं बना सकती, नहीं तो Address already in use त्रुटि मिलेगी। उदाहरण के लिए, नीचे दिए गए कोड को असंभव है।

use Workerman\Worker;
use Workerman\Connection\TcpConnection;
require_once __DIR__ . '/vendor/autoload.php';

$worker = new Worker();
// 4 प्रक्रियाएँ
$worker->count = 4;
// प्रत्येक प्रक्रिया शुरू करने के बाद वर्तमान प्रक्रिया में एक नया Worker जोड़ें
$worker->onWorkerStart = function($worker)
{
    /**
     * 4 प्रक्रियाएँ शुरू होने पर 2016 पोर्ट के Worker का निर्माण करें
     * जब worker->listen() निष्पादित होता है, तो Address already in use त्रुटि होगी
     * यदि worker->count=1 है, तो कोई त्रुटि नहीं होगी
     */
    $inner_worker = new Worker('http://0.0.0.0:2016');
    $inner_worker->onMessage = 'on_message';
    // सुनने का कार्य। यहाँ Address already in use त्रुटि आएगी
    $inner_worker->listen();
};

$worker->onMessage = 'on_message';

function on_message(TcpConnection $connection, $data)
{
    $connection->send("hello\n");
}

// कार्यकर्ता चलाएँ
Worker::runAll();

यदि आपका PHP संस्करण >= 7.0 है, तो आप Worker->reusePort=true सेट कर सकते हैं, इस प्रकार से कई उप-प्रक्रियाएँ समान पोर्ट के लिए Worker बना सकती हैं। नीचे दिए गए उदाहरण को देखें:

use Workerman\Worker;
use Workerman\Connection\TcpConnection;
require_once __DIR__ . '/vendor/autoload.php';

$worker = new Worker('text://0.0.0.0:2015');
// 4 प्रक्रियाएँ
$worker->count = 4;
// प्रत्येक प्रक्रिया शुरू करने के बाद वर्तमान प्रक्रिया में एक नया Worker जोड़ें
$worker->onWorkerStart = function($worker)
{
    $inner_worker = new Worker('http://0.0.0.0:2016');
    // पोर्ट पुन: उपयोग सेट करें, समान पोर्ट के Worker को सुनने के लिए बनाया जा सकता है (PHP>=7.0 की आवश्यकता है)
    $inner_worker->reusePort = true;
    $inner_worker->onMessage = 'on_message';
    // सुनने का कार्य। सामान्य सुनना त्रुटि नहीं देगा
    $inner_worker->listen();
};

$worker->onMessage = 'on_message';

function on_message(TcpConnection $connection, $data)
{
    $connection->send("hello\n");
}

// कार्यकर्ता चलाएँ
Worker::runAll();

उदाहरण php बैकएंड समय पर क्लाइंट को संदेश धकेलना

सिद्धांत:

  1. एक websocket Worker स्थापित करें, जो क्लाइंट को लंबे समय तक जुड़े रहने के लिए बनाए रखता है।

  2. websocket Worker के अंदर एक text Worker बनाएँ।

  3. websocket Worker और text Worker एक ही प्रक्रिया में हैं, जिससे क्लाइंट कनेक्शन को साझा करना आसान होता है।

  4. एक अलग php बैकएंड सिस्टम text प्रोटोकॉल के माध्यम से text Worker से संवाद करता है।

  5. text Worker websocket कनेक्शन को संभालकर डेटा धकेलने का कार्य करता है।

कोड और कदम

push.php

<?php
use Workerman\Worker;
use Workerman\Connection\TcpConnection;
require_once __DIR__ . '/vendor/autoload.php';

// एक वर्कर कंटेनर को प्रारंभ करें, 1234 पोर्ट को सुनें
$worker = new Worker('websocket://0.0.0.0:1234');

/*
 * ध्यान दें कि यहाँ प्रक्रियाओं की संख्या को 1 पर सेट करना चाहिए
 */
$worker->count = 1;
// कार्यकर्ता प्रक्रिया प्रारंभ होने के बाद एक text `Worker` बनाएँ ताकि आंतरिक संचार पोर्ट खोला जा सके
$worker->onWorkerStart = function($worker)
{
    // आंतरिक पोर्ट खोलें, जिससे आंतरिक सिस्टम डेटा धकेल सके, Text प्रोटोकॉल प्रारूप टेक्स्ट + नए लाइन वर्ण
    $inner_text_worker = new Worker('text://0.0.0.0:5678');
    $inner_text_worker->onMessage = function(TcpConnection $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 से कनेक्शन के मैपिंग को संरक्षित करने के लिए एक नई प्रॉपर्टी जोड़ें
$worker->uidConnections = array();
// जब कोई क्लाइंट संदेश भेजता है, तो निष्पादित होने वाला कॉलबैक फंक्शन
$worker->onMessage = function(TcpConnection $connection, $data)
{
    global $worker;
    // जांचें कि क्या वर्तमान क्लाइंट ने पहले से ही UID सत्यापित किया है, यानी क्या UID सेट किया गया है
    if(!isset($connection->uid))
    {
       // यदि सत्यापित नहीं किया गया है, तो पहले पैकेट को uid मानते हैं (यहाँ प्रदर्शन के लिए, असली सत्यापन नहीं किया गया है)
       $connection->uid = $data;
       /* uid से कनेक्शन के मैपिंग को संरक्षित करें, जिससे uid के माध्यम से कनेक्शन को आसानी से खोजा जा सके,
        * विशेष रूप से uid पर डेटा धकेलने को कार्यान्वित करने के लिए
        */
       $worker->uidConnections[$connection->uid] = $connection;
       return;
    }
};

// जब कोई क्लाइंट कनेक्शन डिस्कनेक्ट करता है
$worker->onClose = function(TcpConnection $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::runAll();

बैकएंड सेवा शुरू करें
php push.php start -d

फ्रंटएंड को धकेलने के लिए जावास्क्रिप्ट कोड

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);
};

बैकएंड संदेश धकेलने का कोड

// आंतरिक धकेलने के पोर्ट पर सॉकेट कनेक्शन स्थापित करें
$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);