آموزش WebSocket در PHP

آموزش WebSocket در PHP

بسم الله الرحمن الرحیم

آموزش WebSocket


یکی از دوستان در خصوص استفاده از WebSocket در زبان PHP سول پردسیده بودند که چطور می توانند از این ویژگی استفاده کنند. در همین خصوص سعی کردیم یک مثال در این رابطه آماده کنیم.

WebSocket یک ویژگی از HTML5 برای ایجاد یک socket connections مابین یک مرورگر و یک سرور است. تمامی اطلاعات WebSocket به جای روش معمول درخواست و پاسخ HTTP به صورت مستقیم توسط یک socket ارسال می شوند، این ارتباط یک سریعتر و دائمی مابین سرور و مرورگر خواهد بود.

برای این که موضوع مشخص شود اجازه دهید یک مثال چت ساده را مانند ASP.NET MVC که انجام دادیم، در این جا نیز پیاده سازی کنیم.

آموزش WebSocket در PHP

بسم الله الرحمن الرحیم

آموزش WebSocket


یکی از دوستان در خصوص استفاده از WebSocket در زبان PHP سول پردسیده بودند که چطور می توانند از این ویژگی استفاده کنند. در همین خصوص سعی کردیم یک مثال در این رابطه آماده کنیم.

WebSocket یک ویژگی از HTML5 برای ایجاد یک socket connections مابین یک مرورگر و یک سرور است. تمامی اطلاعات WebSocket به جای روش معمول درخواست و پاسخ HTTP به صورت مستقیم توسط یک socket ارسال می شوند، این ارتباط یک سریعتر و دائمی مابین سرور و مرورگر خواهد بود.

برای این که موضوع مشخص شود اجازه دهید یک مثال چت ساده را مانند ASP.NET MVC که انجام دادیم، در این جا نیز پیاده سازی کنیم.

آموزش WebSocket در PHP


Browser Support

مرورگر های قدیمی از WebSockets پشتیبانی نمی کنند بنابراین شما نیاز دارید از یک مرورگر جدید که قابلیت پشتیبانی از ویژگی های WebSocket را دارد استفاده کنید.

لطفا برای مشاهده وضعیت تمامی مرورگرها در پشتیبانی از WebSocket به این لینک مراجعه کنید.

شروع کار با WebSocket در PHP

پیاده سازی سمت کلاینت در WebSocket بسیار ساده است. کل کدها از چند متد و رویداد ساده تشکیل شده اند. زیر برای مثال به کد زیر نگاه کنید:

//create a new WebSocket object.
websocket = new WebSocket("ws://localhost:9000/daemon.php");
websocket.onopen = function(evt) { /* do stuff */ }; //on open event
websocket.onclose = function(evt) { /* do stuff */ }; //on close event
websocket.onmessage = function(evt) { /* do stuff */ }; //on message event
websocket.onerror = function(evt) { /* do stuff */ }; //on error event
websocket.send(message); //send method
websocket.close(); //close method

برای باز کردن connection یک socket ما به سادگی دستور new WebSocket(ws://SERVER URL) را فراخوانی می کنیم.
زمانی که socket از چندین protocol مختلف برای ارتباطات استفاده می کند، ما باید از دستور ws:// به جای دستور http:// استفاده کنیم و به دنبال این دستور Host، port number و صفحه مربوطه را مشخص کنیم.

آموزش WebSocket در PHP

بعد از باز شدن connection، ما نیاز داریم چندین event handler را برای  بررسی وضعیت connection، خطاها و پیام ها ایجاد کنیم.
•    WebSocket(wsUri) یک شی WebSocket جدید ایجاد می کند
•    Onopen این رویداد زمانی که یک connection ایجاد می شود، اتفاق می افتد.
•    Onclose این رویداد زمان که یک connection بسته می شود، اتفاق می افتد.
•    Onmessage این رویداد زمان که کلاینت داده ای را از سرور دریافت می کند، اتفاق می افتد.
•    Onerror این رویداد زمان که یک خطا رخ دهد، اتفاق می افتد.
•    send(message) داده ها را به سرور انتقال می دهد البته باید قبل از آن connection باز شده باشد.
•    close() این دستور برای بستن connection جاری مورد استفاده قرار می گیرد.

شما می توانید WebSocket را با استفاده از jQuery در صفحه خود پیاده سازی کنید.

$(document).ready(function(){
    //Open a WebSocket connection.
    var wsUri = "ws://localhost:9000/daemon.php";  
    websocket = new WebSocket(wsUri);
   
    //Connected to server
    websocket.onopen = function(ev) {
        alert('Connected to server ');
    }
   
    //Connection close
    websocket.onclose = function(ev) {
        alert('Disconnected');
    };
   
    //Message Receved
    websocket.onmessage = function(ev) {
        alert('Message '+ev.data);
    };
   
    //Error
    websocket.onerror = function(ev) {
        alert('Error '+ev.data);
    };
   
     //Send a Message
    $('#send').click(function(){
        var mymessage = 'This is a test message';
        websocket.send(mymessage);
    });
});

آموزش برنامه چت در PHPx

در مثال بالا نحوه ایجاد یک WebSocket و سپس اضافه کردن event handler ها و درنهایت ارسال اطلاعات از طریق متد websocket.send() را بررسی کردیم. زمانی که ما یک مجموعه از اطلاعات (مانند نام کاربری، پیام و...) در برنامه چت خود هستیم، ما باید اطلاعات را به صورت JSON تبدیل و سپس به سرور ارسال کنیم.

$(document).ready(function(){
    //create a new WebSocket object.
    var wsUri = "ws://localhost:9000/daemon.php";  
    websocket = new WebSocket(wsUri);
   
    websocket.onopen = function(ev) { // connection is open
        $('#message_box').append("<div class=\"system_msg\">Connected!</div>"); //notify user
    }

    $('#send-btn').click(function(){ //use clicks message send button  
        var mymessage = $('#message').val(); //get message text
        var myname = $('#name').val(); //get user name
       
        if(myname == ""){ //empty name?
            alert("Enter your Name please!");
            return;
        }
        if(mymessage == ""){ //emtpy message?
            alert("Enter Some message Please!");
            return;
        }
       
        //prepare json data
        var msg = {
        message: mymessage,
        name: myname,
        color : '<?php echo $colours[$user_colour]; ?>'
        };
        //convert and send data to server
        websocket.send(JSON.stringify(msg));
    });
   
    //#### Message received from server?
    websocket.onmessage = function(ev) {
        var msg = JSON.parse(ev.data); //PHP sends Json data
        var type = msg.type; //message type
        var umsg = msg.message; //message text
        var uname = msg.name; //user name
        var ucolor = msg.color; //color

        if(type == 'usermsg')
        {
            $('#message_box').append("<div><span class=\"user_name\" style=\"color:#"+ucolor+"\">"+uname+"</span> : <span class=\"user_message\">"+umsg+"</span></div>");
        }
        if(type == 'system')
        {
            $('#message_box').append("<div class=\"system_msg\">"+umsg+"</div>");
        }
       
        $('#message').val(''); //reset text
    };
   
    websocket.onerror   = function(ev){$('#message_box').append("<div class=\"system_error\">Error Occurred - "+ev.data+"</div>");};
    websocket.onclose   = function(ev){$('#message_box').append("<div class=\"system_msg\">Connection Closed</div>");};
});

در زیر کد HTML ما برای سیستم چت مشخص شده است، از یک سری CSS برای کار استفاده کردیم که آنها را در اینجا قرار ندادیم اما در آخر مطلب لینک دانلود مثال موجود است و شما می توانید آن را دانلود و از آن استفاده کنید.

<div class="chat_wrapper">
<div class="message_box" id="message_box"></div>
<div class="panel">
<input type="text" name="name" id="name" placeholder="Your Name" maxlength="10" style="width:20%"  />
<input type="text" name="message" id="message" placeholder="Message" maxlength="80" style="width:60%" />
<button id="send-btn">Send</button>
</div>
</div>

ساخت Chat Server در PHP Socket

در حال حاضر برنامه چت ما آماده است که آن را بر روی سرور خود قرار دهیم. اما برای اجرای نرم افزار خود نیاز به یک سرور داریم که به صورت تمام وقت در حال اجرا باشد و WebSocket handshaking، ارسال و دریافت اطلاعات از صفحات چت و همچنین مدیریت client ها را بر عهده گیرد. برای این کار ما باید یک daemon script در PHP ایجاد کنیم. همه می دانند که PHP برای ساخت صفحات dynamic مورد استفاده قرار می گیرد اما اکثر افراد از این مبحث که PHP می تواند برنامه هایی برای اجرا شدن پس زمینه (background) غافل هستندف این برنامه ها daemon قلمداد می شوند.

نصب WebSocket Server

یک local web server مانند WAMP یا XAMPP نصب کنید. من از XAMPP server استفاده می کنم. XAMPP server اجازه می دهد با استفاده از shell option یک daemon script را اجرا کنیم. من نمی دانم WAMP هم این امکانات به این صورت دارد یا خیر، از روش های دیگری استفاده می کند اما از این مقاله می توانید برای کار با WAMP در خصوص daemon script استفاده کنید.
طبیعتا شما می خواهید از این کد بر روی یک سرور در اینترنت استفاده کنیم، پس بهتر است سرور خود را چک کنید و ببینید که آیا سرور به شما اجازه اجرا daemon scripts  و  shell commands را می دهد یا خیر.
برای این کار از پشتیبانی شرکتی که از آن Host را اجاره کرده اید کمک بگیرید، البته معمولا کمی باید وقت صرف کنید تا به نتیجه برسید، چون متاسفانه این مشکلات را همه شرکت های Hosting دارند.

آموزش WebSocket در PHP

مراحل راه اندازی PHP Socket

ما از PHP socket برای ساخت WebSocket برنامه چت خود استفاده می کنیم، برای این کار باید مراحل زیر را انجام دهیم:


1- باز کردن socket
2- مقید کردن (Bind) به یک آدرس
3- گوش دادن به connection های ورودی
4- قبول کردن درخواست های connection
5- WebSocket Handshake (یک مرحله در تمامی اتصالات شبکه ای است که دو سنمت اتصال سرعت و سایر پارامترهای یکدیگر را بررسی می کنند تا به یک توافق برای انجام ارسال و دریافت و سایر پارامتر ها نظیر سرعت، وقفه ها، طول هر فریم و.. برسند)
6- اطلاعات Unmask/Encode می شوند

Open socket

در ابتدا یک socket با استفاده از دستور socket_create(Domain, Type, Protocol) در PHP ایجاد می کنیم. مثال:

//Create TCP/IP sream socket and return the socket resource
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

Bind address

یک نام  را به socket مقید می کنیم. این کار باید قبل از ایجاد connection و استفاده از دستورsocket_connect()  یا socket_listen() انجام شود.

// Bind the source address
socket_bind($socket, 'localhost');

Listen incoming connections

وقتی ما یک socket ایجاد کردیم باید به درخواست های اتصال توسط سرور گوش دهیم

// Listen to incoming connection
socket_listen($socket);

Accept connections

با استفاده از این دستور با درخواست های اتصال موافق می کنیم.

// Accept new connections
socket_accept($socket);

Handshake

Client با ارسال یک درخواستWebSocket handshake  به یک connection در سرور خودش را معرفی می کند. یک درخواست handshake شامل یک Sec-WebSocket-Key، که یک مقدار 16 byte ایی فقط خواندنی، با base64 encode می باشد، است. سرور این key را می خواند و به آن یک String (“258EAFA5-E914-47DA-95CA-C5AB0DC85B11″) به صورت hash شده با SHA1 اضافه می کند و سپس key را در Sec-WebSocket-Accept که به صورت base64 encode شده است به Client ارسال می کند.

آموزش WebSocket در PHP

پاسخ Handshake در PHP

$secKey = $headers['Sec-WebSocket-Key'];
$secAccept = base64_encode(pack('H*', sha1($secKey . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));
$upgrade  = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" .
"Upgrade: websocket\r\n" .
"Connection: Upgrade\r\n" .
"WebSocket-Origin: $host\r\n" .
"WebSocket-Location: ws://$host:$port/deamon.php\r\n".
"Sec-WebSocket-Accept:$secAccept\r\n\r\n";
socket_write($client_conn,$upgrade,strlen($upgrade));


Unmasking/Encoding data frames

پس از عملیات handshaking، client می تواند شروع به ارسال و دریافت پیام کند اما تمامی پیام های به صورت encrypt شده خواهند بود. اگر ما بخواهیم این پیام ها را نمایش دهیم باید هر پیام را unmask شود. مطلبی در خصوص این فرایند در این جا نوشته شده است که می توانید آن را مطالعه کنید.

Starting Chat Server

فایل برنامه که در زیر قرار داده شده است را دانلود کنید. این برنامه شامل دو فایل PHP به نام هایindex.php  و  server.php می باشد. با استفاده از Shell command-line در برنامه XAMPP بخش سرور WebSocket برنامه چت خود را به وسیله دستور زیر اجرا کنید.

php -q c:\path-to-server\server.php

هنگامی که سرور برنامه چت شما اجرا شد، شما می توانید با استفاده از مرورگر خود صفحه index.php  را اجرا و برنامه را تست کنید.

دانلود برنامه چت با PHP

نظرات

  • Hannah Martinez
    امید اقاخانی
    دو شنبه 11 دی 1278 - 0:00

    سلام
    جناب ممنون از اموزشتون
    فقط یه سوالی
    به این وب سوکت میشه از زبان های دیگه مثل جاوا برای اندروید هم استفاده کرد
    مثلا یه برنامه فروشگاهی رو اماده کرد که از وب سوکت اطلاعات رو بیرون بکشه؟

    • Judith Bell
      پاسخ
      اسماعیلشیدایی
      دو شنبه 11 دی 1278 - 0:00

      با عرض سلام


      به این روشی که فرموده اید وب سرویس طبیعتا گفته می شود و آخرین و بهترین نوع وب سرویس ها، web API می باشد که به صورت کامل در وب سایت آموزش داده شده است.

      موفق باشید.

  • Hannah Martinez
    امیر
    دو شنبه 11 دی 1278 - 0:00

    سلام واقعاً عالی بود ، خیلی ممنون.
    یک سوال! چطور میتونم با کمی تغییر دو آرایه از لیست کلاینت ها بسازم و هر موقع که لازم شد به یکی از این کلاینت لیست ها پیام ارسال کنم؟
    فرض کنید 2 اتاق چت وجود دارد و گاهی نیاز است پیام به کلاینت های اتاق یک و گاهی برای اتاق دو ارسال شود!
    ممنون میشم اگه کمکم کنید.

  • Hannah Martinez
    آرش
    دو شنبه 11 دی 1278 - 0:00

    واسه نوشتن چنین مطالبی که خیلی کم فارسیش پیدا میشه باید واقعا ازتون تشکر کرد، امیدوارم ادامه داشته باشه

    • Judith Bell
      پاسخ
      اسماعیلشیدایی
      دو شنبه 11 دی 1278 - 0:00

      با عرض سلام
      خواهش می کنم من از نیز از لطف شما متشکرم

  • Hannah Martinez
    AlirReza
    دو شنبه 11 دی 1278 - 0:00

    به نام خدا سلام ، ممنون از اموزش جالبتون . میشه بگین چجوری میتونم اول user &pass بگیرم و بعدش سوکت رو به کاربر وصل کنم؟

  • Hannah Martinez
    مهندس
    دو شنبه 11 دی 1278 - 0:00

    میگم جاب مندس اینایی که شما گفتی نمیدونم چرا دقیقا مث اینایی هس که اینجاس https://www.sanwebe.com/2013/05/chat-using-websocket-php-socket حالا بگذریم اگه یکی نخواد اصلا از جی کوری استفاده کنه چی؟

    • Judith Bell
      پاسخ
      اسماعیلشیدایی
      دو شنبه 11 دی 1278 - 0:00

      سلام
      وقتتون بخیر
       

      این دقیقا همان مقاله است که در اینجا پیاده سازی شده است.

      برای انجام برنامه های Real Time یا باید از دستورات Nodejs استفاده کنید یا SignalR و یا دستورات را با jquery  شبیه سازی کنید، برای اینکه در وب شما قدرت Full Duplex را ندارید. در خصوص آموزش SignalR می توایند به بخش دوره ی آموزشی SignalR مراجعه کنید.

      موفق و پیروز باشید

نظرات یا سوالات خودرا با ما درمیان بگذارید

0912 097 5516 :شماره تماس
0713 625 1757 :شماره تماس