۳۳ دیدگاه نظر امیر صالحی
آموزش برنامه نویسی سوکت در PHP
آموزش برنامه نویسی سوکت در PHP

حتما برای یک بار هم که شده شاهد نرم افزارهایی مثل تلگرام، واتس اپ و ...  بودید و به احتمال زیاد از نسخه‌ی وب آن‌ها نیز استفاده کرده‌اید. آیا تا به حال به این فکر کرده‌اید که این نرم افزارها چگونه نوشته می‌شوند و می‌توانند در مرورگر شما مثل یک نرم افزار در کامپیوتر شما عمل کنند؟ اگر به این سوال یا به سوالات مشابه برخورد کرده‌اید با ما در این مقاله همراه باشید تا برنامه نویسی سوکت در PHP را به شما آموزش دهیم.

Web Socket چیست؟

به طور کلی وب سوکت (Web Socket) یک پروتکل ارتباطی مداوم و دو طرفه از مرورگر کاربر به سرور است. ارتباط وب سوکتی به این صورت است که درخواست به صورت Handshake (ارتباط Handshake به ارتباط دو تلفن معروف است که با یکدیگر اطلاعات رد و بدل می‌کنند) از پروتکل HTTP کاربر به سمت سرور ارسال می‌شود تا ارتباط بین این دو دستگاه را پایدارتر کند. Web Socket از پروتکل کاملا متفاوت استفاده می‌کند که آن را در مقابل HTTP منحصر به فرد می‌کند. قبل از هر چیزی باید اول HTTP و Web socket را با یکدیگر مقایسه کنیم تا متوجه بشویم برنامه نویسی وب سوکت در PHP به چه کاری می‌آید.

HTTP چگونه کار می‌کند؟

اگر شما یک توسعه دهنده باشید قطعا می‌دانید که HTTP یا HTTPS چگونه کار می‌کنند، ما در این بخش سعی می‌کنیم اشاره‌ی کوچکی به آن کنیم اما اگر می‌خواهید دقیق‌تر بدانید حتما مقالات پروتکل HTTP چیست؟ و پروتکل https چیست؟ را بخوانید.

به طور کلی درخواست (Request) شما نیاز به پاسخ دارد و شما از سرور (Server) می‌خواهید که تمامی پیام‌هایی که وجود دارد را به ترتیب به شما بر گرداند. همچنین باید گفت که HTTP دارای درخواست‌های  (Request) مختلفی هست از جمله POST - GET - PUT و ... که هر کدام از آن‌ها برای هدف‌های مختلفی استفاده می‌شوند. برنامه نویسی سوکت در PHP

اما در Web socket شما احتیاجی ندارید درخواستی ارسال کنید تا پاسخ‌ها را به ترتیب دریافت کنید بلکه شما دارای یک ارتباط دو طرفه پایدار هستید و شما فقط به این نیاز دارید که به داده‌ها گوش (Listen) دهید. به طور واضح‌تر شما فقط منتظر این می‌مانید که سرور به شما پیامی بدهد تا بگوید " هی، یه پیام جدید اومده! ".

برنامه نویسی سوکت در PHP

کاربرد‌های Web socket

تا الان متوجه شدیم که Web socket چگونه کار می‌کند ولی باید کاربرد برنامه نویسی وب سوکت در PHP را نیز بدانیم تا درک بیشتری از آن داشته باشیم.

Real-time application

RTA که مخفف عبارت Real-Time Application است به اپلیکیشن‌هایی معروف است که فریم‌ (Frame) به فریم زمان کار می‌کنند که کاربر احساس می‌کند نرم‌ افزار در لحظه اجرا می‌شود. تاخیر زمانی باید درون این نوع اپلیکیشن‌ها به پایین‌ترین حد ممکن برسد و به کاربر این احساس را بدهد که انگار با یک نرم‌ افزار در PC خود در حال کار کردن است.

اپلیکیشن‌‌های چت کاربران

به احتمال زیاد با نرم افزارهای پیام رسان تحت وب کار کرده‌اید مثل تلگرام، واتس اپ و ... که این‌طور نرم‌افزارها نیز به وسیله‌ی Web socket توسعه داده شده‌اند و شما درون نرم افزارهای پیام رسان تحت شبکه این احساس را می‌کنید که کاملا یک ارتباط پایدار دارید.

اینترنت اشیاء

IoT مخفف عبارت Internet of Thing و به معنای اینترنت اشیاء است، اما شاید برای‌تان جالب باشد زمانی که شما می‌خواهید برای مثال وضعیت وسایل‌های مختلف خانه‌ی خود که، با اینترنت اشیاء کنترل می‌کنید را مشاهده کنید، این وضعیت و یا Status آن‌ها باید در لحظه به شما گزارش شود و شما شاهد و نظاره‌گر آن‌ها باشید. در اینجا نیز Web socket نقش مهمی دارد.

بازی‌های چند نفره‌ی آنلاین

یکی از بهترین راه‌کارهای راه‌اندازی بازی‌های چند نفره آنلاین استفاده کردن از Web socket است چون همان‌طور که  اشاره شد شما دارای یک ارتباط پایدار و دو طرفه هستید و می‌توان این بازی‌ها را در این پروتکل به آسانی توسعه و مورد استفاده قرار داد.

چه زمانی باید از Web socket دوری کنیم؟

استفاده از Web socket بستگی به پروژه‌ی شما دارد که از آن استفاده کنید یا خیر؟ برای مثال زمانی که شما در حال توسعه یک CMS یا یک سیستم مدیریت محتوا هستید لازم به این نیست که شما از Web socketها استفاده کنید، در بخش قبلی ما نیز اشاره کردیم که کاربرد دقیق Web socketها چه زمانی است.

پیاده سازی نرم افزار چت با PHP

به جذاب‌ترین بخش این مقاله‌ی آموزشی رسیدیم. قرار است یک نرم افزار چت ساده با برنامه نویسی سوکت در PHP پیاده سازی کنیم. تا الان متوجه شدیم که وب سوکت‌ها چه هستند و دقیقا چه کار می‌کنند و الان نوبت به آن رسیده است که از آن استفاده کنیم.

پکیج Ratchet

قبل از اینکه دست به کد نویسی ببریم باید به شما توضیح بدهیم که قرار است از چه چیزی استفاده کنیم، ما در این آموزش از پکیج Ratchet استفاده می‌کنیم تا بتوانیم خیلی راحت‌تر با Web socket در PHP کار کنیم. برای استفاده و نصب این پکیج ما نیاز داریم که از Composer استفاده کنیم.

نصب و راه اندازی Composer

به طور کلی Composer یک ابزار مدیریت وابستگی برای PHP است که باعث می‌شود شما درگیر مدیریت وابستگی بین پکیج‌ها و کتابخانه‌های PHP نشوید.

اگر سیستم عامل کاربر Windows باشید می‌توانید با کلید کردن بر روی لینک Composer فایل نصبی Composer را دانلود کنید و آن را نصب کنید. اما اگر از لینوکس یا مک استفاده می‌کنید می‌توانید به وب سایت Composer installation مراجعه کنید و دستورات را به تربیت انجام دهید تا Composer را در سیستم عامل خود داشته باشید.

راه اندازی پروژه چت با PHP

یک پوشه به نام websocket یا هر چیز دیگری که دوست دارید در XAMPP و یا WAMP ایجاد می‌کنیم تا پروژه‌مان را درون این پوشه توسعه بدهیم. بعد از ساخت پوشه آن را در ویرایشگر خود باز کنید.

یک فایل به نام composer.json ایجاد کنید ساختار json زیر را درونش قرار دهید.
{
    "require": {
        "cboden/ratchet": "^0.4.1"
    },
    "autoload": {
       "psr-4": {
         "ChatApp\\": "src"
       }
    }
 }

در ساختار بالا که برای composer است ما در بخش require نام و ورژن پکیج Ratchet را آورده‌ایم تا بتوانیم آن را نصب کنیم، در بخش autoload ما از psr-4 برای لود کردن فایل‌هایمان استفاده کرده‌ایم، قاعده‌ی کلی این است که شما درون psr-4 یک نام را قرار می‌دهید که به عنوان namespace پیش فرض شناخته می‌شود و در مقابل نام پوشه را می‌دهید که قرار است فایل‌های PHP درون آن قرار بگیرید و به طور خودکار لود شوند که ما در اینجا src قرار داده‌ایم و قرار است کدهای PHP را درون پوشه‌ی src قرار دهیم.

بعد از قرار دادن ساختار json بالا commnad line را در پوشه‌ی خود باز کنید و دستور زیر را وارد کنید تا پکیج برای شما نصب شود، فرایند نصب ممکن است مقداری طول بکشد. (به یاد داشته باشید که باید VPN خود را روشن داشته باشید)

composer install
بعد از اتمام نصب یک پوشه به نام vendor و یک فایل به نام composer.lock برای شما ساخته شده است.

همان‌طور که گفته شد یک پوشه به اسم src بسازید و بعد از ساخت پوشه درون آن یک فایل PHP به نام chat ایجاد کنید. خارج از پوشه ‌یsrc یعنی درون پوشه‌ی اصلی پروژه دو فایل دیگر به نام‌های server.php و index.php ایجاد کنید که در ادامه قرار است کدهای برنامه نویسی سوکت در PHP را در آن‌ها بنویسیم. در نهایت ساختار پوشه‌های شما به شکل زیر می‌باشد.

ساخت نرم افزار چت با PHP

توسعه‌ی فایل chat.php

ابتدا تمامی کدهای درون فایل chat.php را قرار می‌دهیم و بعد از آن به تحلیل خط به خط کدها می‌پردازیم.
<?php
namespace ChatApp;
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
class Chat implements MessageComponentInterface {
    protected $clients;
    public function __construct() {
        $this->clients = new \SplObjectStorage;
    }
    public function onOpen(ConnectionInterface $conn) {
        // Store the new connection to send messages to later
        $this->clients->attach($conn);
        echo "New connection! ({$conn->resourceId})\n";
    }
    public function onMessage(ConnectionInterface $from, $msg) {
        foreach ($this->clients as $client) {
            if ($from !== $client) {
                // The sender is not the receiver, send to each client connected
                $client->send($msg);
            }
        }
    }
    public function onClose(ConnectionInterface $conn) {
        // The connection is closed, remove it, as we can no longer send it messages
        $this->clients->detach($conn);
        echo "Connection {$conn->resourceId} has disconnected\n";
    }
    public function onError(ConnectionInterface $conn, \Exception $e) {
        echo "An error has occurred: {$e->getMessage()}\n";
        $conn->close();
    }
}

کدهای بالا تمامی کدهای درون فایل chat.php است و همان‌طور که قابل مشاهده است این پروژه‌ی کوچک را ما به صورت شئ گرایی توسعه می‌دهیم، حال نوبت به آن رسیده است که کدها را تحلیل کنیم.

در خط اول تگ php را باز کرده‌ایم تا بتوانیم در آن فایل، کدهای php خود را توسعه بدهیم. در خط بعدی که کد زیر است.

namespace ChatApp;
use Ratchet\MessageComponentInterface; 
use Ratchet\ConnectionInterface;

ما ابتدا namespace فایل خود را مشخص کرده‌ایم که این کار باید همیشه در اولین خط فایل php انجام شود، همان‌طور که در فایل composer.json ما مشخص کردیم که namespace پیش فرض ChatApp است ما نیز در اینجا namespace این کلاس را ChatApp قرار داده‌ایم.

در خط‌های بعدی ما دو کلاس را می‌بینیم که آن‌ها را use کرده‌ایم، در اصل این کلاس‌ها را بعد از نصب کردن پکیچ Retchat ما در دسترس داریم و باید با استفاده از این دو کلاس و کلاس‌های دیگر که به آن‌ها خواهیم پرداخت نرم‌افزار خود را توسعه دهیم.

class Chat implements MessageComponentInterface {

در خط بعدی ما یک کلاس تعریف کرده‌ایم و نام آن را Chat قرار داده‌ایم که این نام دلخواه است و هر نامی دوست دارید می‌توانید بگذارید اما در ادامه ما کلاس MessageComponentInterface که در بالا use کرده بودیم را implements کرده‌ایم، ما زمانی که یک کلاس Interface مانند کلاس بالا را implements می‌کنیم باید تمامی متدهای (Method) درون کلاس implements شده را در کلاس فرزند پیاده سازی کنیم. کلاس فرزند همان کلاسی است که یک کلاس دیگر را implements و یا extends می‌کند.

تمامی متدهایی که ما درون کلاس آورده‌ایم متدهای همان کلاس MessageComponentInterface است که ما implements کرده‌ایم.

protected $clients;

در خط بعدی ما یک متغیر به نام clients با سطح دسترسی protected ایجاد کرده‌ایم که در ادامه کد از این متغیر استفاده خواهیم کرد.

public function __construct() { 
    $this->clients = new \SplObjectStorage; 
}

در خط بعدی ما یک متد construct__ تعریف کرده‌ایم که به متد سازنده نیز معروف است، زمانی که ما از کلاس Chat یک شی جدید ایجاد کنیم اولین متدی که به طور پیش فرض صدا زده می‌شود متد construct__ است. ما درون کلاس construct__ متغیری که در بالا تعریف کرده‌ بودیم، متغیر clients را به ساختار object تبدیل کرده‌ایم تا بتوانیم در ادامه مقادیر آبجکتی (object) متفاوتی درونش ذخیره و استفاده کنیم. برای اینکه به متغیرهای کلاس دسترسی داشته باشیم درون متدهای کلاس، از کلمه‌ی کلیدی this$ استفاده می‌کنیم.

public function onOpen(ConnectionInterface $conn) {
        // Store the new connection to send messages to later
        $this->clients->attach($conn);
        echo "New connection! ({$conn->resourceId})\n";
}

تابع onOpen زمانی اجرا می‌شود که یک کاربر بخواهد از نرم افزار ما استفاده کند که ما درون این تابع یک conn که همان connection یا اتصال است را با کمک تابع attach درون clients اضافه کرده‌ایم تا تمامی لیست کاربرانی را که در نرم افزار ما هستند را داشته باشیم و بتوانیم مدیریت‌شان کنیم. در خط بعدی ما یک پیغام را echo کرده‌ایم که نوشته‌ایم یک اتصال جدید برقرار شده است و آیدی (Id) کسی که متصل شده است را نیز به دنباله آن چاپ کرده‌ایم.

public function onMessage(ConnectionInterface $from, $msg) {
        foreach ($this->clients as $client) {
            if ($from !== $client) {
                // The sender is not the receiver, send to each client connected
                $client->send($msg);
            }
        }
}

تابع onMessage زمانی اجرا می‌شود که پیامی ارسال شود، این تابع دارای دو پارامتر به نام‌های from و msg است که from اطلاعات کسی را در اختیار دارد که پیام ارسال کرده است و متغیر msg حاوی پیام ارسال شده است. درون تابع onMessage یک حلقه‌ی foreach وجود دارد، این حلقه بر روی متغیر clients که ما در بدنه‌ی کلاس تعریف کرده‌ایم پیماش می‌کند که متغیر clients نیز دارای اطلاعات تمامی کاربرانی است که به نرم افزار ما متصل شده‌اند یا در حال استفاده از آن هستند.

درون حلقه‌ی foreach یک شرط قرار داده‌ایم تا پیام ارسالی را به بقیه کاربران به جز client ارسال کند. اگر بخواهیم یک مثال قابل فهم‌تر بزنیم این است که برای مثال من یک پیامی را ارسال کرده‌ام (from) این پیام باید برای همه ارسال شود به جز خودم، که این پیام را ارسال کرده‌ام (client).

public function onClose(ConnectionInterface $conn) {
        // The connection is closed, remove it, as we can no longer send it messages
        $this->clients->detach($conn);
        echo "Connection {$conn->resourceId} has disconnected\n";
}

تابع بعدی ما تابع onClose است، این تابع زمانی اجرا می‌شود که کاربری ارتباطش را با سرور ما قطع می‌کند یا به عبارتی از نرم افزار ما خارج می‌شود. به عنوان ورودی این تابع conn را دریافت می‌کند که همان کسی است که تا الان به سرور ما متصل بوده است. در بدنه‌ی تابع نیز ما به کمک تابع detach که دقیقا کار مخالف تابع attach را انجام می‌دهد، در اینجا اتصال را قطع می‌کند و اطلاعات کاربر را از درون متغیر clients حذف می‌کند. و در نهایت نیز یک پیام چاپ می‌کند که می‌گوید ارتباط connection قطع شده است.

 public function onError(ConnectionInterface $conn, \Exception $e) {
        echo "An error has occurred: {$e->getMessage()}\n";
        $conn->close();
}

آخرین تابع ما به نام onError است، این تابع زمانی اجرا می‌شود که خطایی در برنامه رخ بدهد. این تابع به عنوان ورودی conn که همان connection ما توسط کاربر است و یک Exception را دریافت می‌کند تا بتوانیم خطای خود را مدیریت کنیم. در بدنه‌ی تابع ابتدا با echo نوع خطا را چاپ می‌کنیم و در خط بعدی اتصال کاربر را با تابع close می‌بندیم تا ارتباطش قطع شود.

توسعه‌ی فایل server.php

طبق روال قبلی ابتدا کدهای این فایل را قرار می‌دهیم و شروع به تحلیل خط به خط آن می‌کنیم.
<?php
require 'vendor/autoload.php';
use Ratchet\Server\IoServer;
use ChatApp\Chat;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
$server = IoServer::factory(
    new HttpServer(
        new WsServer(
            new Chat()
        )
    ),
    8080
);
$server->run();
طبق قوانین گذشته برای اینکه بتوانیم کد PHP توسعه دهیم باید تگ php?> را باز کنیم.
require 'vendor/autoload.php';

در خط بالا ما فایل autoload کامپوزر (Composer) را require کرده‌ایم که قرار است فایل chat.php را به صورت خودکار require کند تا ما بتوانیم از آن در این صفحه استفاده کنیم.

use Ratchet\Server\IoServer;
use ChatApp\Chat;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
در این بخش ما تمامی کلاس‌هایی را که لازم داریم use کرده‌ایم تا بتوانیم در برنامه از آن‌ها استفاده کنیم.
$server = IoServer::factory(
    new HttpServer(
        new WsServer(
            new Chat()
        )
    ),
    8080
);

در این خط ما از کلاس IoServer که در بالا use کرده‌ایم متد factory را صدا زده ایم و به آن دو ورودی داده‌ایم. در ورودی اول یک نمونه از HttpServer با کمک new ساخته‌ایم و درونش یک WsServer که همان سرور Web socket ما است را نیز با کلمه‌ی کلیدی new ساخته‌ایم، در داخل کلاس WsServer کلاسی که خودمان در فایل chat.php توسعه دادیم را نیز new کرده‌ایم تا بتوانیم از آن استفاده کنیم. به عنوان ورودی دوم باید port را وارد کنیم که در اینجا پورت 8080 را وارد کرده‌ایم.

$server->run();

در ادامه نیز متغیر server که تمامی کلاس‌های مورد نیاز را درون آن new کرده‌ایم را با متد run صدا می‌زنیم تا این سرور اجرا شود.

در نهایت نیز با استفاده از command line خود یا cmd وارد دایرکتوری (Directory) پروژه‌ی خود شوید و دستور  زیر را وارد کنید.

composer dumpautoload

این باعث می‌شود که autoload کامپوز (Composer) پروژه، فایل‌هایی را که در اختیارش قرار داده بودیم را لود کند تا ما بتوانیم از آن‌ها استفاده کنیم.

توسعه‌ی فایل index.php

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Chat</title>
    <!-- CSS only -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
</head>
<body>
    <div class="container">
        <div class="row">
            <ul class="msg-list">
            </ul>
        </div>
        <form method="post" id="chatForm">
            <div class="form-group">
                <label for="message"></label>
                <input type="text" name="message" id="message" class="form-control" />
            </div>
            <div>
                <input type="submit" id="subBtn" class="btn btn-info" value="send">
            </div>
        </form>
    </div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script> 
    $(document).ready(function() {
        var conn = new WebSocket('ws://localhost:8080');
        var chatForm = $('#chatForm');
        var userMessage = $("#message");
        var msgList = $('.msg-list');
        chatForm.on('submit', function(e){
            e.preventDefault();
            var message = userMessage.val();
            conn.send(message);
            msgList.prepend("<li style='color:blue;'>" + message +"</li>");
        });
        conn.onopen = function(e) {
            console.log("Connection stablished");
        }
        conn.onmessage = function(e) {
            console.log(e.data);
            msgList.prepend("<li style='color:red;'>" + e.data + "</li>");
        }        
    });
    </script>
</body>
</html>
در صفحه‌ی index.php ما یک فرم خیلی ساده داریم که ظاهر آن به شکل زیر است. ساخت نرم افزار چت با PHP
<div class="container">
        <div class="row">
            <ul class="msg-list">
            </ul>
        </div>
        <form method="post" id="chatForm">
            <div class="form-group">
                <label for="message"></label>
                <input type="text" name="message" id="message" class="form-control" />
            </div>
            <div>
                <input type="submit" id="subBtn" class="btn btn-info" value="send">
            </div>
        </form>
</div>

اگر به فرم بالا دقت کنید، فرم ما درون یک div با کلاس container که یک کلاس bootstrap است قرار دارد تا فرم ما را در بر بگیرد و یک position مشخصی داشته باشد. یک تگ با کلاس row وجود دارد که درونش یک تگ ul قرار دارد که کلاس سی اس اس msg-list دارد،این تگ قرار است در بر گیرنده‌ی پیام‌های ما باشد.

فرمی که در بالا وجود دارد action ندارد به این معنا که قرار است اطلاعات را به همین صفحه ارسال کند، method فرم ما نیز POST است تا اطلاعاتمان را در این method رد و بدل کنیم. درون فرم نیز یک input وجود دارد که از نوع text است تا ما بتوانیم پیام خود را وارد کنیم و یک input دیگر نیز وجود دارد که از نوع submit است که یک دکمه برای ارسال اطلاعات به حساب می‌آید.

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
به طور پیش فرض ما کد بالا را که cdn جی کوئری (Jquery) است را در صفحه‌ی html قرار داده‌ایم تا بتوانیم از jquery استفاده کنیم.
<script> 
    $(document).ready(function() {
        var conn = new WebSocket('ws://localhost:8080');
        var chatForm = $('#chatForm');
        var userMessage = $("#message");
        var msgList = $('.msg-list');
        chatForm.on('submit', function(e){
            e.preventDefault();
            var message = userMessage.val();
            conn.send(message);
            msgList.prepend("<li style='color:blue;'>" + message +"</li>");
        });
        conn.onopen = function(e) {
            console.log("Connection stablished");
        }
        conn.onmessage = function(e) {
            console.log(e.data);
            msgList.prepend("<li style='color:red;'>" + e.data + "</li>");
        }        
    });
    </script>
و اما کد جاوا اسکریپتی که به ما کمک می‌کند تا از Web socket استفاده کنیم.
$(document).ready(function() {
این کد به این معنی است که هر موقع صفحه‌ی index ما به طور کامل load شد کدهای درون این بلاک شروع به اجرا کردن کنند.
var conn = new WebSocket('ws://localhost:8080');

با استفاده از کلاس WebSocket که در جاوا اسکریپت وجود دارد آدرس و پورت خود را مشخص کرده‌ایم و یک شئ از آن را با new ساخته‌ایم و در متغیر conn قرار داده‌ایم که در ادامه از آن استفاده می‌کنیم.

var chatForm = $('#chatForm');
var userMessage = $("#message");
var msgList = $('.msg-list');

با استفاده از Jquery المان‌های (Element) مورد نظرمان را دریافت کرده‌ایم که در ادامه قرار است درون آن‌ها یا مقداری قرار دهیم یا مقداری را برداریم.

chatForm.on('submit', function(e){
            e.preventDefault();
            var message = userMessage.val();
            conn.send(message);
            msgList.prepend("<li style='color:blue;'>" + message +"</li>");
});

در کد بالا ما با استفاده از Jquery و با استفاده از متد on مشخص کرده‌ایم که هر موقع submit شد به این معنی که هر موقع روی دکمه‌ی submit کلید کردند تابع بی نام که به عنوان پارامتر دوم به on داده‌ایم اجرا شود. به تابع بی نام e را به عنوان ورودی داده‌ایم، با استفاده از این متغیر e که وجود دارد می‌توانیم تمامی event یا رویدادهایی که رخ می‌دهد کنترل کنیم. برای مثال ما در اینجا از تابع preventDefault از submit شدن تابع جلوگیری کرده‌ایم تا عملیاتی که می‌خواهیم را انجام دهیم.

در ادامه‌ی کد،  مقدار یا value قرار داده شده‌ی کاربر درون input را استخراج کرده‌ایم، که input را ما در بالا با استفاده از Jquery دریافت کرده‌ بودیم و درون متغیر userMessage قرار داده‌ بودیم و حال با استفاده از تابع val مقدار قرار داده شده درون input را دریافت کرده‌ایم و درون متغیر message قرار داده‌ایم. در ادامه ما با استفاده از شئ conn که قبلا ساخته بودیم پیام را با کمک تابع send به سمت سرور ارسال می‌کنیم.

در خط بعدی نیز ما با استفاده از Jquery یک li که حاوی پیام وارد شده است به لیستی که در صفحه‌ی html خود داشتیم اضافه می‌کنیم و رنگ متن پیغام را آبی کرده‌ایم تا متوجه شویم کدام پیام را ما ارسال کرده‌ایم.

conn.onopen = function(e) {
            console.log("Connection stablished");
}

با استفاده از تابع onopen در شئ conn می‌توانیم تشخیص بدهیم که یک نفر نرم افزار ما را اجرا کرده است، پس برای تست در console یک پیغام تستی حاوی Connection stablished که به معنی اتصال برقرار شده است را log می‌کنیم.

conn.onmessage = function(e) {
            console.log(e.data);
            msgList.prepend("<li style='color:red;'>" + e.data + "</li>");
} 

تابع بعدی onmessage زمانی اجرا می‌شود که یک پیام ارسال شود، این تابع یک پارامتر e دریافت می‌کند، همان‌طور که گفتم رویدادهای ما درون آن است، درون e یک تابع به اسم data داریم که پیام ارسال شده توسط کاربر را در بر دارد. ما این پیام را با استفاده از Jquery به لیستمان درون html اضافه می‌کنیم و رنگ آن را نیز با قرمز استایل دهی می‌کنیم، توجه داشته باشید e.data که پیام کاربر نیز درونش است را ارسال می‌کنیم.

اجرای نهایی پروژه

با استفاده از cmd یا terminal ویرایشگر خود دستور زیر را اجرا کنید. اگر از cmd استفاده می‌کنید باید حتما وارد دایرکتوری (Directory) پروژه شوید.

php server.php
با استفاده از دستور بالا ما پوشه server.php را run می‌کنیم.

برای تست برنامه نویسی سوکت در PHP ، دو مرورگر جدا باز کنید و آدرس پروژه خود را که در XAMPP یا WAMP شما وجود دارد وارد کنید، به خاطر داشته باشید که Apache شما باید start خورده باشد. حال شروع کنید به پیام دادن در دو مرورگر و شاهد یک پیام رسان ساده و جذاب خواهید بود.

 
 
جمع‌بندی

در این مقاله به آموزش برنامه نویسی سوکت در PHP پرداختیم. و متوجه شدیم که کارایی Web socket چه است. در ادامه ما برای خود یک پروژه تعریف کردیم و شروع به توسعه دادن آن کردیم، با پکیجی به اسم Ratchet آشنا شدیم و یاد گرفتیم که چگونه می‌شود با این پکیج کار کرد و حتی تمامی متدهای آن را تحلیل کردیم. در انتها نیز به جاوا اسکریپت نیازمند شدیم و از متد Web socket در جاوا اسکریپت نیز استفاده کردیم تا پروژه‌مان تکمیل شود. امیدوارم که از این آموزش بهره کافی را برده باشید و با ما در آموزش‌های دیگر همراه باشید.

اگر به یادگیری بیشتر در زمینه‌ی PHP علاقه داری، با شرکت در دوره‌ی آموزش PHP در کمتر از یک سال به یک متخصص PHP تبدیل می‌شوی که آماده‌ی استخدام، دریافت پروژه، کسب درآمد و یادگیری مباحثی مثل لاراول هستی.
۳۳ دیدگاه
ما همه سوالات و دیدگاه‌ها رو می‌خونیم و پاسخ میدیم
۲۱ مرداد ۱۴۰۲، ۲۰:۳۴

سلام خیلی عالی بود . تنها یک موردی هست وقتی php server.php رو اجرا کردیم سیستم درست عمل می‌کنه ولی وقتی ترمینال رو ببندیم سرور متوقف میشه . حالا تو لوکال مشکلی نیست ولی تو سرور اصلی این میشه دردسر . کلی گشتم ولی چیزی پیدا نکردم چطوری کاری کنم به محض اینکه سرور php ران شد دستور php server.php در پس زمینه اجرا بشه و اون اسکریپتم دیگه قطع نشه ؟ اگر سر نخی هم بدید میرم دنبالش متشکرم از مجموعه خوبتون

نازنین کریمی مقدم ۱۹ شهریور ۱۴۰۲، ۱۰:۴۹

درود <a href="https://serverfault.com/questions/76875/how-to-run-script-via-ssh-that-doesnt-end-when-i-close-connection" target="_blank" rel="noopener nofollow ugc">راهکار توقف نکردن اسکریپت در سرور</a>

۲۷ بهمن ۱۴۰۱، ۰۷:۵۲

سلام برا من قبلا server.php اجرا میشد . اما با اینکه هیچ تغییری در کد ندادم اما وقتی php server.php رو تایپ میکنم هیچ اتفاقی نمیفته انگار داره پروسه میکنه .

۱۳ بهمن ۱۴۰۱، ۰۶:۰۳

سلام سوال داشتم فوری کسی هست جواب بده ایا این اموزشی که گفتین برای این تمرین خوبه یک برنامه socket programming بنویسید که بعد از ارتباط کلاینت با سرور و احراز هویت یک فایل بر روی سوکت ایجاد شده ارسال نماید

نازنین کریمی مقدم ۱۴ بهمن ۱۴۰۱، ۲۰:۵۲

درود بله مناسب هست اما باید به php مسلط باشید و بخشهایی مثل احراز هویت رو باید جدا خودتون اضافه کنید. <a href="https://stackoverflow.com/questions/8748865/php-socket-programming?rq=1" rel="nofollow ugc">این تاپیک</a> رو بررسی کنید، کاربران نمونه کدهای مفیدی در این خصوص رو قرار دادند.

۱۹ شهریور ۱۴۰۱، ۱۰:۲۸

عالی

۱۹ اردیبهشت ۱۴۰۱، ۰۸:۲۶

سلام. در فایرفاکس این خطا رو نشان میده. چطور مشکل رو میتونم برطرف کنم؟ Firefox can’t establish a connection to the server at ws://localhost:8080/.

نازنین کریمی مقدم ۱۹ اردیبهشت ۱۴۰۱، ۰۸:۲۸

درود پاسخ پذیرفته شده <a href="https://stackoverflow.com/questions/48904150/firefox-can-t-establish-a-connection-to-the-server-at-ws-localhost8080" target="_blank" rel="noopener nofollow ugc">این تاپیک</a> رو مطالعه بفرمایید.

۱۹ اردیبهشت ۱۴۰۱، ۱۰:۲۶

متاسفانه این راه حل جواب نداد. راه حل دیگه ای نداره؟

نازنین کریمی مقدم ۱۹ اردیبهشت ۱۴۰۱، ۱۳:۳۵

<a href="https://stackoverflow.com/questions/6172364/cant-establish-a-connection-to-the-server-at-ws-localhost8000-socket-server" target="_blank" rel="noopener nofollow ugc">این تاپیک</a> رو هم بررسی کنید.

۰۹ مهر ۱۴۰۱، ۰۶:۲۱

متاسفانه این قسمت رو توضیح ندادن. بعد از اتمام کار از طریق cmd با دستور cd به محلی که فایل server.php هست برید و دستور زیر رو بزنید ( مثلا اگه فایل توی مسیر c://wamp/www هست : c://wamp/www&amp;gt;php server.php دقت کنید بین php و server.php یه فاصله space هست. بذارید یه سری اطلاعات میاد. در نهایت کادر فایروال باز میشه که ازتون می‌پرسه که مطمئن هستید می‌خواید فایروال بلاکش نکنه. دوتا گزینه رو تیک بزنید و تموم.

۱۱ بهمن ۱۴۰۰، ۱۶:۳۲

سلام من ارتباط وب سوکتم برقرار نمیشه نمیدونم مشکل از کجاست یه بار میگه شما از پروتکل https برای ارسال دستور غیر ایمن ws استفاده میکنین. از یه طرف خودم به باز پورت سایتم شک دارم در صورتی که پشتیبانی هاستم میگه بازه پورت موردی نداره ممنون میشم اگه بتونین کمک کنین

نازنین کریمی مقدم ۱۲ بهمن ۱۴۰۰، ۰۹:۴۲

سلام پیشنهاد میکنم در اولین قدم، جاهای مختلف لاگ کنید و گام به گام کدتون رو بررسی کنید. نود درصد مشکلات معمولا به همین شیوه رفع میشن.

۲۷ تیر ۱۴۰۱، ۱۲:۳۲

سلام به خاطر اینه شما روی ویندوز پروژه رو اجرا کردید و به حروف کوچک و بزرگ حساس نیست این مقاله یه باگ داشت و اونم اینه که فایل Chat.php با حرف کوچیک شروع کرد و این توی ویندوز مشکلی نداره ولی وقتی رو هاست آپلود میکنی به خاطر اینکه سیستم عامل لینوکس هست خطا میده یه لاگ بگیرید متوجه میشید

۲۸ دی ۱۴۰۰، ۱۴:۴۸

چطور اول نامش رو بگیریم و وقتی ارسال کرد نامش رو بنویسه؟

نازنین کریمی مقدم ۲۹ دی ۱۴۰۰، ۱۰:۲۵

درود کافیه این نام رو در یک متغیر ریخته و در سرور ذخیره کنید و دفعه بعدی با گت کردن هرجایی که میخواید نشونش بدید. در همین راستا اینم بگم که این کار اغلب در بستر جیسون انجام میشه.

babak_maziar ۰۱ آذر ۱۴۰۰، ۱۱:۳۰

دوستان ما متدی به نام put یا delete نداریم، شما اگر با ajax دیتا ارسال کنی و اسم متد رو مثلا بذاری ABCD و توی بک اند $_SERVER رو چک کنی میبینی که اسم متد همون ABCD هست که مسلما بی معناست. وقتی شما از put یا delete یا هر متد من در آوردی دیگری استفاده می‌کنی، فقط اسم رو تغییر دادی، و پروتکل امنیتی که داره استفاده میشه همون پروتکل پیش فرض (get) هست که از نا امنیش هم نگم برات. این یک باگ مسخرست که توی فریم ورک‌های اماده وجود داره و متاسفانه از اونجایی که اکثر برنامه نویس‌ها فقط کاربرد‌ها رو یاد میگیرن و به مفاهیم توجه نمی‌کنند، ازش بی اطلاع هستند.

Nazanin KarimiMoghaddam ۰۳ آذر ۱۴۰۰، ۰۷:۳۳

درود بنده متاسفانه به این مبحث مسلط نیستم که اظهار نظر کنم، اما ممنون از اینکه تجربه خودتون در اختیار بقیه میگذارید :)

۲۷ تیر ۱۴۰۱، ۱۲:۲۷

سلام این متد‌ها فقط واسه امینت نیست اگه رست فول ای پی آی کار کرده باشید کاربردشو متوجه میشید

siros fakhri ۲۱ مهر ۱۴۰۰، ۱۱:۲۹

ممنون بابت آموزش. امکان اینکه بتونیم یه کانال خصوصی بسازیم وجود داره؟

نازنین کریمی مقدم ۲۱ مهر ۱۴۰۰، ۱۳:۲۷

درود منظورتون دقیقا چیه؟ متوجه سوالتون نشدم.

رسول ۱۱ مهر ۱۴۰۰، ۰۶:۵۳

عالی

تربچه ۱۱ مهر ۱۴۰۰، ۰۶:۵۱

عالی بود

تایماز مصطفایی ۱۵ تیر ۱۴۰۰، ۰۹:۱۸

سلام ای کاش به صورت ویدیوی آموزش ظبط میشد

نازنین کریمی مقدم ۰۳ مرداد ۱۴۰۰، ۲۰:۴۳

درود. بابت تاخیر در پاسخگویی پوزش میطلبیم. درخواستتون رو به تیم انتقال دادم در صورت درخواستهای بیشتر کاربران، حتما اضافه میکنیم. در حال حاضر آموزش ویدیویی در دوره متخصص php سایت وجود داره.

رضا ۱۹ آذر ۱۳۹۹، ۲۲:۰۶

سلام وقت بخیر قسمت پرسش و پاسخ رو پیدا نکردم اگر امکان داره لینکشو بفرستید.و مورد دیگه این هست که اگر روی سرور یا هاست قرار باشه اجرا بشه باید پورت 8000 باز باشه و از نود جی اس پشتیبانی بشه درسته؟

رضا ۲۲ آبان ۱۳۹۹، ۱۹:۱۱

سلام و عرض ادب خدمت آقای صالحی امکان داره آموزش بدید چطوری در هاست از وب سوکت استفاده کنیم و آیا پورت‌ها تغییر می‌کنه. و اگر آیدی تلگرامتون رو بدید تا در ارتباط باشم و مشکلم حل بشه ممنون میشم

امیر صالحی ۲۸ آبان ۱۳۹۹، ۱۹:۳۸

سلام و احترام چشم اگه این امکان بود بنده حتما یه آموزش در این رابطه ایجاد میکنم. اگه داخل بخش پرسش و پاسخ سوالتونو مطرح کنید بنده سریع‌تر پاسخ میدم

asadolahi ۲۸ مهر ۱۳۹۹، ۱۷:۰۴

با سلام من یک چت روم مطابق با کدهای شما پیاده سازی کردم، در لوکال هاست مشکلی نداشت ولی زمانی که آن را در سرور مجازی بارگذاری کردم، client نمی‌تواند به server وصل شود و خطای websocket handshake time out می‌دهد. ممنون میشم که راهنمایی ام کنین. تشکر

رضا ۰۳ مهر ۱۳۹۹، ۱۹:۵۹

سلام ممنون از مقاله خوبتون الان برای اینکه داخل لوکال بشه چت کرد نیازه هست دستور php server.php اجرا بشه و اگر بخوام روی سایت بارگذاری کنم چطوری باید دستور php server.php رو اجرا کرد؟

امیر صالحی ۲۸ آبان ۱۳۹۹، ۱۹:۳۵

سلام و احترام فکر کنم نیازی نیست دستوری توی سرور اجرا کنید چون شما داخل سرور هستید

محمدرضا رحیمی ۰۸ شهریور ۱۳۹۹، ۰۹:۵۸

با سلام و احترام: اول از هر چیزی تشکر بابت مقالات خوبتون. سوالی برام پیش اومده: درون فایل chat.php هنگامی که متدهای اینترفیس رو implements کردیم یکسری پارامتر ورودی تعریف کرده ایم که قبل از اونها نام یک اینترفیس آورده شده، این کار مثل مشخص کردن data type هستش؟ (که مشخص شده این متغیر از نوع این اینترفیس می‌باشد). اصلا به چه منظور این کار را انجام می‌دهیم؟

امیر صالحی ۱۲ شهریور ۱۳۹۹، ۱۶:۰۳

سلام و احترام به شما مرسی که وقت گذاشتی و این مقاله رو خوندی. این نوع پارامترها خیلی استفاده می‌شه مخصوصا توی فریم ورک ها، حالا چرا؟ توی متدهایی که شما توی نرم افزارت استفاده میکنی گاها نیاز داری که پارامتر‌های ورودیت از نوع یک کلاس خاص باشه تا بتونی از تمامی ویژگی هاش استفاده کنی، یه جورایی شبیه به اینه که شما یک شئ از اون کلاس رو توی متدت داری و می‌تونی از تمامی خصوصیاتش و یا متدهاش استفاده کنی که یکی از راهکارهای بسیار مناسب برای جلوگیری کردن از "ارث بری"‌های اضافه توی شئ گرایی هستش. سوالی که پرسیدیو خیلی دوست داشتم و بهت یه مقاله معرفی میکنم تا درک بیشتری ازش داشته باشی. این مقاله رو از دست نده: <a href="https://www.amitmerchant.com/reasons-use-composition-over-inheritance-php/" rel="nofollow ugc">composition</a>

  • Web Socket چیست؟
  • HTTP چگونه کار می‌کند؟
  • کاربرد‌های Web socket
  • چه زمانی باید از Web socket دوری کنیم؟
  • پیاده سازی نرم افزار چت با PHP
اشتراک گذاری مقاله در :