php : شرح ال websocket


التعليقات

يوجد خطأ في عرض المقال حجم العرض كبير عن الشاشة .

أنصحك بأن تكتب المقال فى مدونة خارجية مخصصة للكتابة و يمكنك التعديل عليها ومراجعة الأخطاء .. و تضع الرابط هنا بعد ذلك

على سبيل المثال .. لديك منشر

مقال ممتاز و لو كنت أضفت له إستخدام الجافا سكربت فى التعامل مع قواعد البيانات سيكون أكثر أفادة ... لأن هذه المشكلة التى يتوقع عندها الجميع فى بداية تعاملهم .. و أنا توقفت مرتين بسبب أستخدامى للويندوز و صعوبة تركيب بعض المكتبات ... و لكن فى النهاية أنهيت الأمر على ubuntu بكل سهولة .

ماذا تقصد باستخدام javascript مع قواعد البيانات هل تقصد indexedDB او websql

ام التعامل مع قاعدة بيانات علي السيرفر ؟

أقصد مثلاً أنك لو تقوم بعمل تطبيق محادثة (شات) .. يجب عليك تخزين العبارات المتداولة بين الأفرد .. حتى إذا أراد أحدهم فتح المحادثة فيما بعد فيرى الحوار الذى دار بينه و بين الطرف الآخر

تحتاج إلى redis و بعض المكتبات الأخرى لعمل ذلك ..

و هذا حل آخر

اه نعم يوجد اكثر من طريقة لفعل هذا بدون استخدام مكتبات خارجية منها استخدام قواعدة بيانات mysql او قاعدة بيانات اخري و عمل نظام اعضاء وعند فتح اتصال ارسال رمز الي السيرفر يتم توليده بعد تسجيل الدخول وهو غير ثابت وبعد التأكد من انه مستخدم ويتم حفظ البيانات بشكل عادي

او توفير العناء وحفظ البيانات في المتصفح لكن سيكون هناك مشكلة اذا المستخدم استخدم متصفح آخر .

لا يتم حفظ البيانات عن طريق PHP ولكن عن طريق javascript ... لأن PHP ليس لها علاقة بالأمر .. إلا أنها سيرفر sockets فقط

أى أنك إذا كنت تتبع الخطوات التى حدثتنا عنها فى المقالة أعلاه ... فإن سيرفر ال sockets الذى أنشأته بال PHP هو مختلف عن سيرفرك الذى عليه المعالجة برغم أنهما على نفس الجهاز .. إلا أن كل منهم يستمع ل port مختلف

لذلك إما تخزن بالجافا سكربت أو تقوم بإختراع طريقة للحديث بين سيرفرين عن طريق curl مثلاً

ما اعنيه موضح هنا أكثر :

لا يستطيع ان يعمل connect على نفس ال database من ال socket ؟

يمكن ذلك بدون مشاكل ان شاء الله لكن تذكر socket لايدعم الجلسات cookies

تقصد بال cookies ال session أيضا ، بعني فعليا لا يمكن التحقق من ال user الا عن طريق التأكد منه من ناحية ال socket و ال javascript غير آمنة الاّ أنّ التأكد سيكون مختلف كصنع session و حفظه بال database عند تسجيل الدخول اليس كذلك؟

seession تعتمد علي الcookies حيث تقوم بحفظ id لكل مستخدم في cookies والبيانات تحفظ في ملف

الحل عمل نظام مخصص مثلاً رمز تقوم بانشاءه بعد تحميل الصفحة لكل مستخدم يحفظ في القاعدة وتأكد منه بعد الاتصال هذه فكرة مبدئية .

عزيزى .. الحل الذى ذكرته غير صحيح بالمره و ذلك لأنك تتعامل مع Client ID المستخدم الذى تم توليده من قبل ال socket و ليس id المستخدم الحقيقى الموجود فى قاعدة البيانات فى جدول users مثلاً ... فكيف ستربط بينهما .. لا وسيلة لذلك ... إلا بالطرق التى أخبرتك عنها مسبقاً ..

حل آخر و لكنه غير صحيح عملياً ...

عند الدخول للصفحة الخاصة بالشات مثلاً .. يتم الحصول على ال client id الذى تم توليده للمستخدم من قبل ال socket ثم بال ajax ترسلها للسيرفر على أن هذا هو نفس المستخدم الحالى .. و لكن سيكون هناك نوع من التأخير لإنتظار عملية المصادقة هذه .. و بعد عملية المصادقة عند كل ارسال لل socket .. تقوم بالإستعلام عن id المستخدم الحقيقى من خلال client_id الآخر و تقوم بإدراج الرسالة ب id المستخدم الحقيقى فى قاعدة البيانات ..

و لكن المشكلة أن تقوم بفتح متصفح جديد مثلاً و تسجل الدخول سيتم عمل مصادقة جديدة تحذف القديمة ... لذلك يمكنك إستخدام جدول وسيط تحفظ فيه كافة المصادقات التى يتم إنشاؤها و من خلالها يكون جميعهم صالحين للإستخدام

ملحوظه : لو هناك سرعة فى الكتابة أو عدة أشخاص موجودين .. ستجد الرسائل حفظت بشكل غير مرتب فى قاعدة البيانات .. لأن السيرفر سيأخذ وقتاً فى الإستعلام الزائد الخاص بمعرفة ال id الحقيقى

يمكن ارسال مع كل رسالة id المستخدم المعتمد مع ال الرمز او ال hash الذي حصل عليه المستخدم عند تسجيل الدخول و في حال فتح المستخدم مرة أخرى يضاف الترميز و لا يحذف القديم.

لكن أرى أنه عند فتح الحساب ينشىء session باسم ال id و يرسل ال id مع كل رسالة و يتم التحقق من ال session عن طريق ال curl أفضل من استعمال ال database

هذا كان قصدي

الحل عمل نظام مخصص مثلاً رمز تقوم بانشاءه بعد تحميل الصفحة لكل مستخدم يحفظ في القاعدة وتأكد منه بعد الاتصال هذه فكرة مبدئية .

لكن ايضأً انا افضل في الشات sse

websocket جيدة في نظام التنبيهات لكن ان دعمت ال cookies فيما بعد ستكون افضل بكثير .

لاصديقي اذكر اني فعلت ذلك من قبل انظر مثال حفظ الرسالة بملف اذاً يمكن حفظها في قاعدة البيانات

<?php
    include(__dir__."/class.PHPWebSocket.php"); // استدعاء المكتبة
    set_time_limit(0); // لالغاء اقصي مدة للطلب
    $server = new PHPWebSocket();
    /*
     * الحدث عند اتصال المستخدم بالسيرفر
     * $id هو رقم ثابت للمستخدم يتغير ولايتكرر في اتصالان معاً
    */
    $server->bind("open",function($id){
        global $server;
        $server->wsSend($id,"انه يعمل"); // ارسال رسالة للمستخدم يجب ان يكون رقم ال $ip الخاص به موجود
    });

    /*
     * عند قدوم رسالة من الخادم
    */
    $server->bind("message",function($id,$mss){
        global $server;
        $server->wsSend($id,"تم ارسال رسالتك بنجاح !"); // ارسال رسالة للمرسل
        foreach($server->wsClients as $clientId => $client)// جميع المستخدمين المتصلين بالسيرفر
            if($clientId != $id)// المستخدم ليس المرسل
                $server->wsSend($clientId,$mss); // ارسال الرسالة لباقي المستخدمين
        $file = fopen(__dir__."/mss","w+");
        fwrite($file,"{$id} : {$mss}");
        fclose($file);
    });

    // تشغيل السيرفر
    $server->wsStartServer(
        gethostbyname("localhost")// هنا يمكن وضع اي بي سنستخدم هذه الدالة لجلب اي بي localhost 
        ,"9999" // منفذ السيرفر ضع اي رقم يجب ان لايكون مستخدم في برنامج اخر وسيستخدم فيما بعد في javascript
    );  
?>

في حال استخدام websocket في التنبيهات وابقاء المستخدمين متصلين معاً ستقوم ببناء الموقع علي طريقة الصفحة الواحدة

اتقصد بإبقاء المستخدمين متصلين معا ان لا يفصل عند التنقل بين صفحات الموقع؟ اذا نعم ما المانع في الاتصال عند كل صفحة جديدة؟

ان كان شخص يعرف id الشخص الآخر الا يمكنه و ضعه في javascript و يصبح يتلقى و يرسل الرسائل الخاصة بالشخص الآخر؟

اقصد

المانع انه سيختفي عند كل خروج مثلاً ستحدد المستخدمين المتواجدين اثناء تنقل احدهم فانه سيختفي الي حين تحميل الصفحة والاتصال

ال id لايحدد من قبل المتصفح بل يحدد علي حسب عدد المستخدمين مثلا يوجد اربعة اعضاء دخل اخر يكون الاخر 5 وعند خروج احد يكون ال id الخاص به 4 من قبل مكتبة phpwebsocket .

لقد قرأت هذا المقال سابقا و انا ارى لا مانع من أن يعيد الإتصال كل مرة ك فيسبوك بغض النظر ان الفيسبوك يعتمد ال sse مثلا الا ان كان البقاء على اتصال ضروري

آسف لم انتبه ان ال ID غير موجود نهائيا من ناحية المتصفح

لا ينصح به. لأن websockets من دون async io (أو green threads أو co-routines ) لا فائدة منه لأنه does not scale.

ما الذي تنصح يه ادا ....

في حالة ال real time و event based و bi directional communications و web socket تتميز nodejs و socket.io و python gevent حيث تدعم socket.io ايضا.

يعني هل يمكن ان python gevent تعمل مع php ...

لا هما لغتين مختلفتين. أيضا نسيت أن أذكر لغة go فهي أيضا قوية في هذا المجال حاليا هذه اللغات الثلاثة هي الخيار الأفضل nodejs و python مع gevent و go. الموضوع ليس مكتبة تضيفها على اللغة بل اللغة نفسها يجب أن تتبنى الفكرة ومع الأسف php لا تصلح قولا واحدا لتطبق هذا الشيء.

هل يمكن ان يعمل nodeJS جنبا الي جنب معphp وايضا ف موقع اربيا ما هو مطبق ...او بشكل اخر مواقع التي تعمل بلغات غير ما ذكرته كيف يتم تطبيق real time واكبر مثال عنا hsoub.io or facebook

حاسوب ليس real time بمعنى عليك عمل refresh حتى ترى ما هو جديد. بأي حال في حدود علمي هو ليس php.

وإذا كنت تقصد تعمل جنبا إلى جنب يعني من نفس قاعدة البيانات ويكون هناك فصل في الاهتمام فالجواب نعم مثلا تكون الصفحات في php لكن ال js يتحدث مع nodejs لاستلام التنويها ال real time

بخصوص فيسبوك لديهم ال php الخاصة بهم وهو يحول php إلى C وقد تكون الأجزاء ال real time غير مكتوبة به php أو لعلها ليست مكتوبة ب php التي نعرفها.

بخصوص بقية المواقع الحل هو ضخ المزيد من الموارد

لدى مشكلة حقيقة أرجو لو أحد يساعد فيها

فى البداية كل شئ تمام لكن باقى نقطة واحدة وهى كيفيه إيقاف السيرفر بعد تشغيله علما بأنه يكون شغال علطول

وعند محاولة استخدام wsStopServer فإنه لا يقف ايضا

ما الحل ؟!

لأنى اريد التعديل فى الأكواد ولابد من إيقاف السيرفر لتحديث الكود ومن ثم تشغيله مرة أخرى

السلام عليكم

رجاء عندي مشكلة مع WebSocket لتحديث عداد الرسائل المحظورة في موقعي ولم اعر ف الحل

الر سالة : WebSocket connection to 'wss://localhost/ws/blocked' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED

ر ابط الموقع لمعاينة المشكل :

في انتظار مساعدة