अनुबंध को अनुकूलित करने का तरीका
वास्तव में अपने अनुबंध को बनाना एक सरल कार्य है। सरल अनुबंध आमतौर पर दो भागों में विभाजित होते हैं:
- डेटा सीमा को चिन्हित करने वाला पहचानकर्ता
- डेटा प्रारूप परिभाषा
एक उदाहरण
अनुबंध परिभाषा
यहां मान लिया गया है कि डेटा सीमा के चिन्हित करने वाला पहचानकर्ता नई पंक्ति "\n" है (ध्यान दें कि अनुरोध डेटा के भीतर नई पंक्ति नहीं होनी चाहिए), डेटा प्रारूप Json है, उदाहरण के लिए नीचे एक अनुरोध पैकेट है जो इस नियम का पालन करता है।
{"type":"message","content":"hello"}
ध्यान दें कि ऊपर दिए गए अनुरोध डेटा के अंत में एक नई पंक्ति का वर्ण है (PHP में इसे डबल कोट स्ट्रिंग "\n" से दर्शाया गया है), जो एक अनुरोध के अंत का प्रतिनिधित्व करता है।
कार्यान्वयन चरण
Workerman में यदि उपरोक्त अनुबंध को लागू करना है, मान लें कि अनुबंध का नाम JsonNL है, और प्रोजेक्ट MyApp है, तो निम्नलिखित चरणों की आवश्यकता है:
-
अनुबंध फ़ाइल को प्रोजेक्ट के Protocols फ़ोल्डर में रखें, जैसे फ़ाइल MyApp/Protocols/JsonNL.php।
-
JsonNL वर्ग को कार्यान्वित करें,
namespace Protocols;को नामस्थान के रूप में उपयोग करते हुए, तीन स्थैतिक विधियों को लागू करना होगा, जिनका क्रमशः नाम input, encode, और decode है।
ध्यान दें: Workerman इन तीन स्थैतिक विधियों को स्वचालित रूप से कॉल करेगा, पैकेट को विभाजित करने, अनपैक करने और पैक करने के लिए। विशिष्ट प्रक्रिया का संदर्भ निम्नलिखित कार्यान्वयन प्रक्रिया के विवरण से है।
Workerman और अनुबंध वर्ग के बीच इंटरैक्शन प्रक्रिया
- मान लें कि क्लाइंट एक डेटा पैकेट सर्वर को भेजता है, सर्वर डेटा प्राप्त करना शुरू करता है (यह डेटा का एक हिस्सा हो सकता है) और तुरंत अनुबंध के
inputविधि को कॉल करेगा, जिससे इस पैकेट की लंबाई जांची जा सके,inputविधि लंबाई मान$lengthको Workerman ढांचे को लौटाएगी। - Workerman ढांचा प्राप्त
$lengthमान का उपयोग करता है यह निर्धारित करने के लिए कि क्या वर्तमान डेटा बफर में$lengthलंबाई का डेटा प्राप्त हो चुका है, यदि नहीं, तो यह डेटा का इंतज़ार करना जारी रखेगा, जब तक बफर में डेटा की लंबाई$lengthसे कम न हो जाए। - जब बफर में डेटा की लंबाई पर्याप्त हो जाती है, तो Workerman बफर से
$lengthलंबाई का डेटा निकालता है (जिसे पैकेट विभाजन कहते हैं) और अनुबंध कीdecodeविधि को अनपैक करने के लिए कॉल करता है, अनपैक किया गया डेटा$dataहोगा। - अनपैक के बाद, Workerman डेटा
$dataकोonMessage($connection, $data)के रूप में व्यवसाय को प्रसारित करता है, व्यवसाय onMessage में$dataवेरिएबल का उपयोग करके क्लाइंट द्वारा भेजा गया पूरा और अनपैक किया गया डेटा प्राप्त कर सकता है। - जब व्यवसाय
onMessageमें$connection->send($buffer)विधि का उपयोग करके क्लाइंट को डेटा भेजने की आवश्यकता होती है, तो Workerman स्वचालित रूप से अनुबंध कीencodeविधि का उपयोग करके$bufferको पैक करता है और फिर उसे क्लाइंट को भेजता है।
विशिष्ट कार्यान्वयन
MyApp/Protocols/JsonNL.php का कार्यान्वयन
namespace Protocols;
class JsonNL
{
/**
* पैकेट की संपूर्णता की जांच करता है
* यदि पैकेट लंबाई प्राप्त की जा सके, तो बफर में पैकेट की लंबाई लौटाए, अन्यथा 0 लौटाए और डेटा के लिए प्रतीक्षा जारी रखे
* यदि अनुबंध में समस्या है, तो -1 लौटाया जा सकता है, वर्तमान क्लाइंट कनेक्शन के साथ जुड़े रहने के कारण
* @param string $buffer
* @return int
*/
public static function input($buffer)
{
// नई पंक्ति का वर्ण "\n" प्राप्त करें
$pos = strpos($buffer, "\n");
// नई पंक्ति नहीं है, पैकेट लंबाई का पता नहीं लगा सकते, 0 लौटाएं और डेटा का इंतज़ार करें
if($pos === false)
{
return 0;
}
// नई पंक्ति है, वर्तमान पैकेट लंबाई लौटाएं (नई पंक्ति सहित)
return $pos+1;
}
/**
* पैक करता है, जब क्लाइंट को डेटा भेजने के लिए स्वचालित रूप से कॉल किया जाता है
* @param string $buffer
* @return string
*/
public static function encode($buffer)
{
// json में सीरियलाइज करें, और नई पंक्ति को अनुरोध के अंत के चिन्ह के रूप में जोड़ें
return json_encode($buffer)."\n";
}
/**
* अनपैक करता है, जब प्राप्त डेटा बाइट का संख्या input द्वारा लौटाए गए मान (0 से अधिक मान) के बराबर होती है तो स्वचालित रूप से कॉल किया जाता है
* और onMessage कॉल बैक फ़ंक्शन के $data पैरामीटर में पास किया जाता है
* @param string $buffer
* @return string
*/
public static function decode($buffer)
{
// नई पंक्ति को हटाएं, और इसे एक ऐरे में पुनर्स्थापित करें
return json_decode(trim($buffer), true);
}
}
अब, JsonNL अनुबंध लागू किया गया है, इसे MyApp प्रोजेक्ट में उपयोग किया जा सकता है, जैसे निम्नलिखित तरीके से
फाइल: MyApp\start.php
use Workerman\Worker;
use Workerman\Connection\TcpConnection;
require_once __DIR__ . '/vendor/autoload.php';
$json_worker = new Worker('JsonNL://0.0.0.0:1234');
$json_worker->onMessage = function(TcpConnection $connection, $data) {
// $data वह डेटा है जो क्लाइंट द्वारा भेजा गया है, डेटा पहले से JsonNL::decode के माध्यम से संसाधित किया गया है
echo $data;
// $connection->send द्वारा पर्याप्त मात्रा में डेटा भेजने के लिए JsonNL::encode विधि को स्वचालित रूप से पैक किया जाएगा, फिर क्लाइंट को भेजा जाएगा
$connection->send(array('code'=>0, 'msg'=>'ok'));
};
Worker::runAll();
...
सूचना
WorkermanProtocolsनामस्थान के तहत अनुबंधों को लोड करने का प्रयास करेगा, उदाहरण के लिएnew Worker('JsonNL://0.0.0.0:1234')Protocols\JsonNLअनुबंध को लोड करने का प्रयास करेगा।
यदि त्रुटिClass 'Protocols\JsonNL' not foundआती है, तो कृपया ऑटो लोडिंग के संदर्भ में ऑटो लोडिंग कार्यान्वित करने के लिए देखें।
अनुबंध इंटरफ़ेस विवरण
Workerman में विकसित अनुबंध वर्ग को तीन स्थैतिक विधियों को लागू करना चाहिए, input, encode, decode। अनुबंध इंटरफ़ेस विवरण Workerman/Protocols/ProtocolInterface.php में उल्लिखित है, परिभाषित ऐसा है:
namespace Workerman\Protocols;
use \Workerman\Connection\ConnectionInterface;
/**
* अनुबंध इंटरफ़ेस
* @author walkor <walkor@workerman.net>
*/
interface ProtocolInterface
{
/**
* प्राप्त recv_buffer में पैकेट को विभाजित करने के लिए
*
* यदि $recv_buffer में अनुरोध पैकेट की लंबाई प्राप्त होती है तो पूरे पैकेट की लंबाई लौटाएं
* अन्यथा 0 लौटाएं, यह बताने के लिए कि वर्तमान अनुरोध पैकेट की लंबाई प्राप्त करने के लिए अधिक डेटा की आवश्यकता है
* यदि -1 लौटाया गया, तो इसे दूसरे अनुरोध के रूप में गलत माना जाएगा, और कनेक्शन बंद कर दिया जाएगा
*
* @param ConnectionInterface $connection
* @param string $recv_buffer
* @return int
*/
public static function input($recv_buffer, ConnectionInterface $connection);
/**
* पैकेट के लिए解码
*
* यदि input लौटाए गया मान 0 से अधिक है, और Workerman ने पर्याप्त डेटा प्राप्त किया है, तो decode स्वचालित रूप से कॉल किया जाएगा
* फिर onMessage कॉल बैक को ट्रिगर किया जाएगा, और decode द्वारा अनपैक किया गया डेटा onMessage कॉल बैक के दूसरे पैरामीटर को सौंपा जाएगा
* अर्थात जब पूरा क्लाइंट अनुरोध मिलता है, तो decode स्वतः कॉल होता है, व्यावसायिक कोड में मैन्युअल रूप से कॉल करने की आवश्यकता नहीं है
* @param ConnectionInterface $connection
* @param string $recv_buffer
*/
public static function decode($recv_buffer, ConnectionInterface $connection);
/**
* पैकेट के लिए पैक करना
*
* जब क्लाइंट को डेटा भेजने की आवश्यकता होती है, जैसे $connection->send($data); को कॉल करना
* तो $data को encode का उपयोग करके एक बार पैक कर दिया जाएगा, इसे अनुबंध डेटा प्रारूप में बदल दिया जाएगा, फिर क्लाइंट को भेजा जाएगा
* अर्थात क्लाइंट को भेजा गया डेटा स्वचालित रूप से encode द्वारा पैक होता है, व्यावसायिक कोड में मैन्युअल रूप से कॉल करने की आवश्यकता नहीं है
* @param ConnectionInterface $connection
* @param mixed $data
*/
public static function encode($data, ConnectionInterface $connection);
}
ध्यान दें:
Workerman में अनुबंध वर्ग को ProtocolInterface पर आधारित बनाने की कठोर आवश्यकता नहीं है, वास्तव में अनुबंध वर्ग को केवल input, encode, और decode तीन स्थैतिक विधियाँ शामिल करनी होती हैं।