php : شرح ال websocket


التعليق السابق

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

تحتاج إلى 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
    );  
?>