ما هو WebSocket ولماذا هو مطلوب في PHP
يعمل بروتوكول HTTP التقليدي وفق نموذج "طلب-استجابة": يرسل العميل طلبًا، يعالجه الخادم ويعيد الرد. للحصول على بيانات جديدة، يضطر العميل إلى إعادة تحميل الصفحة باستمرار أو استخدام AJAX-polling (طلبات دورية للخادم). هذا النهج يخلق حملاً زائدًا ولا يوفر اتصالاً "حيًا" حقيقيًا.
WebSocket (RFC 6455) هو بروتوكول ينشئ اتصالاً ثنائي الاتجاه دائمًا بين العميل (المتصفح) والخادم. بعد المصافحة (handshake)، يمكن نقل البيانات في كلا الاتجاهين في الوقت الفعلي دون طلبات HTTP متكررة. هذا هو الحل الأمثل لـ:
- الدردشات وتطبيقات المراسلة
- خلاصات الأخبار والإشعارات
- تحرير المستندات بشكل تعاوني
- الألعاب والمزادات
- المراقبة ولوحات المعلومات
يعتقد الكثيرون أن PHP غير مناسبة لمهام الوقت الفعلي بسبب طبيعتها المتزامنة. لكن مع ظهور مكتبات مثل Ratchet و ReactPHP، تغير الوضع بشكل جذري. يمكن لـ PHP العمل بكفاءة مع WebSocket باستخدام بنية موجهة بالأحداث وإدخال/إخراج غير محظور.
بنية تطبيق WebSocket على PHP
قبل كتابة الكود، من المهم فهم كيفية عمل اتصال WebSocket من جانب خادم PHP.
مراحل إنشاء الاتصال
- مصافحة HTTP (handshake): يرسل العميل طلب HTTP خاصًا مع رأس
Upgrade: websocket. يتحقق الخادم من المفتاحSec-WebSocket-Keyويعيد ردًا بالحالة 101 Switching Protocols. - تبديل البروتوكول: بعد المصافحة الناجحة، يتحول الاتصال إلى وضع WebSocket. يتم تبادل البيانات لاحقًا عبر إطارات ثنائية.
- اتصال مزدوج: يمكن للخادم والعميل إرسال الرسائل في أي وقت حتى يتم إغلاق الاتصال من أحد الطرفين.
PHP المتزامن مقابل PHP غير المتزامن
يعمل سكربت PHP العادي بشكل متزامن: طلب واحد - عملية واحدة، بعد الرد ينتهي السكربت. يتطلب WebSocket عملية تعمل باستمرار تستمع إلى المنفذ وتعالج العديد من الاتصالات المتزامنة. هنا يأتي دور ReactPHP - المكتبة التي تنفذ حلقة الأحداث (event loop) لـ PHP.
مكتبة Ratchet مبنية فوق ReactPHP وتوفر واجهة سهلة لإنشاء خوادم WebSocket. تتولى العمل منخفض المستوى مع المآخذ، تحليل الإطارات وإدارة الاتصالات.
التنفيذ العملي: إنشاء دردشة فورية
لننظر في إنشاء دردشة بسيطة على WebSocket باستخدام Ratchet. يمكن تكييف هذا المثال لأي مهام وقت فعلي.
الخطوة 1: تثبيت التبعيات
تأكد من تثبيت Composer (مدير التبعيات لـ PHP). قم بتثبيت Ratchet وتبعياته:
composer require cboden/ratchetالخطوة 2: إنشاء فئة المعالج
لننشئ ملف ChatServer.php الذي سيدير الاتصالات والرسائل:
<?phpnamespace MyApp;
use Ratchet\\MessageComponentInterface;use Ratchet\\ConnectionInterface;
class ChatServer implements MessageComponentInterface{ protected $clients;
public function __construct() { // SplObjectStorage — طريقة مناسبة لتخزين كائنات الاتصال $this->clients = new \\SplObjectStorage; echo "تم تشغيل الخادم!"; }
public function onOpen(ConnectionInterface $conn) { // عميل جديد متصل $this->clients->attach($conn); echo "اتصال جديد: {$conn->resourceId}"; }
public function onMessage(Connectio