السلام عليكم

هل فكرت يوماً بعمل تحديثات للمسخدم مثلاً اخر التنبيهات وهكذا فقمت باستخدام ajax كل ثانية مثلاً ؟ طبعاً ستلاحظ بطء في قدوم التحديثات وضغط علي السيرفر .

الحل باستخدام websocket حيث السيرفر هو من يرسل التحديثات وليس انت من يطلبها

يعتقد البعض ان كتابة websocket باستخدام php صعب لكنها سهلة جداً باستخدام احد المكتبات

متطلبات

  • امكانية الدخول الي سطر الاوامر

  • الشرح سيكون باستخدام هذه المكتبة لسهولتها http://code.google.com/p/php-websocket-server/ او https://github.com/Flynsarmy/PHPWebSocket-Chat/blob/master/class.PHPWebSocket.php

  • الشرح سيعمل علي php 5.3 او اعلي جربته علي php 5.4

اهلا بالعالم

لانشاء سيرفر websocket سنكتب التالي ونحفظه بملف server.php او اي اسم

<?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->wsStartServer(
        gethostbyname("localhost")// هنا يمكن وضع اي بي سنستخدم هذه الدالة لجلب اي بي localhost 
        ,"9989" // منفذ السيرفر ضع اي رقم يجب ان لايكون مستخدم في برنامج اخر وسيستخدم فيما بعد في javascript
    );  

والان تشغيل السيرفر من سطر الاوامر php -f server.php ان لم تجد خطأ ولم يكتب رد فانه يعمل الان الواجهة

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
    </head>
    <body>
        <button id="mkcon">اتصال</button>
        <script type="text/javascript">
            document.querySelector("#mkcon").addEventListener("click",function(){
                if(!WebSocket)
                    alert("متصفح لايدعم websocket");
                else{
                    ws = new WebSocket("ws://localhost:9989");// الاتصال بالسيرفر ادخل نفس المعلومات التي ادخلتها في كود السيرفر
                    ws.addEventListener("open",function(){ // عند الاتصال بالسيرفر
                        alert("تم الاتصال");
                    });
                    ws.addEventListener("message",function(ms){ // عند قدوم رسالة
                        alert(ms.data);
                    });
                }
            });
        </script>
    </body>
</html>

استلام الرسائل وربط المستخدمين معاً

اولا اغلق السيرفر الذي انشاءناه من قبل عن طريق سطر الاوامر يوجد العديد من الطرق مثلاً (9989 هو المنفذ الذي قمنا بتحديده) lsof -i:9989 -n ستجد عدة مخرجات منها pid لسيرفر php اغلقه ( 29606 هو الpid الذي اخرج لي لايكون ثابت , قد تحتاج الي صلاحيات مدير) kill 29606 ثم استبدل كود السيرفر ب

<?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); // ارسال الرسالة لباقي المستخدمين
    });

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

وشغل السيرفر كما علمنا

php -f server.php

ثم كود الواجهة

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
    </head>
    <body>
        <textarea placeholder="ارسال رسالة" disabled="1"></textarea>
        <button id="sendms" disabled="1">ارسال</button>
        <button id="mkcon">اتصال</button>
        <script type="text/javascript">
            document.querySelector("#mkcon").addEventListener("click",function(){
                if(!WebSocket)
                    alert("متصفح لايدعم websocket");
                else{
                    ws = new WebSocket("ws://localhost:9989");// الاتصال بالسيرفر ادخل نفس المعلومات التي ادخلتها في كود السيرفر
                    ws.addEventListener("open",function(){ // عند الاتصال بالسيرفر
                        alert("تم الاتصال");
                        // تفعيل العناصر المغلقة زر الارسال وصندوق الرسالة غير مهم
                        disableded = document.querySelectorAll("[disabled]");
                        for(element=0;element<=disableded.length-1;element++)
                            disableded[element].disabled=0;
                    });
                    ws.addEventListener("message",function(ms){ // عند قدوم رسالة
                        alert(ms.data);
                    });
                    ws.addEventListener("close",function(){
                        alert("تم اغلاق الاتصال");
                    });
                }
            });
            document.querySelector("#sendms").addEventListener("click",function(){
                if(!ws)
                    alert("قم بالاتصال اولاً");
                else{
                    text = document.querySelector("textarea").value;
                    if(!text)
                        alert("ادخل رسالة اولاً");
                    else 
                        ws.send(text);
                }
            });
        </script>
    </body>
</html>

طبعاً يوجد استخدامات اخري لل websocket وهذه كانت امثلة فقط

ملاحظات

  • websocket لايدعم الجلسات cookies

  • في حال استخدام ssl سيكون البروتوكول هو wss بدلاً من ws

  • بعض الاستضافات لاتدعم sockets لذا يفضل تخصيص سيرفر

  • لدعم المتصفحات القديمة يوجد مكتبات علي github ل javascript تستخدم ال flash وطرق اخري

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

  • في حال عدم امكانية الدخول الي سطر الاوامر او عدم وجود دعم socket استخدم sse قد اشرحه في درس مقبل

الي الان انتهي الدرس في حال واجهت مشكلة ارسلها لي .