<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های میلاد رحیمی</title>
        <link>https://virgool.io/feed/@miladrahimi</link>
        <description>مهندس نرم افزار @ اسنپ</description>
        <language>fa</language>
        <pubDate>2026-04-15 04:40:02</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/6593/avatar/JDc4kK.jpg?height=120&amp;width=120</url>
            <title>میلاد رحیمی</title>
            <link>https://virgool.io/@miladrahimi</link>
        </image>

                    <item>
                <title>آموزش ساخت سرور های Gateway و Bastion</title>
                <link>https://virgool.io/@miladrahimi/%D8%A2%D9%85%D9%88%D8%B2%D8%B4-%D8%B3%D8%A7%D8%AE%D8%AA-%D8%B3%D8%B1%D9%88%D8%B1-%D9%87%D8%A7%DB%8C-gateway-%D9%88-bastion-tw5ho6xpuwd6</link>
                <description>معمولا برای راه‌اندازی یک Bare-metal (سرور اختصاصی) برای چند اپلیکیشن یا یک اپلیکیشن با مقیاس متوسط یا بزرگ از تعداد بیش از یک ماشین مجازی (Virtual Machine / VM) استفاده می‌شود تا سرویس ها، امکانات مختلف مانند سرور گیت و ایمیل، و یا Node های Cloud را بتوان روی VM های مختلف راه‌اندازی کرد.هر یک از VM های یک سرور می‌توانند دارای Public IP باشند و بطور مستقل از اینترنت در دسترس باشند، اما در این صورت علاوه بر نیاز به Public IP به تعداد VM ها و عدم انعطاف پذیری، حفظ امنیت VM ها نیز مشکل خواهد بود. یک معماری مرسوم که در این آموزش به آن می‌پردازیم، ساخت یک شبکه خصوصی (Private Network) بر روی VM ها است. در این معماری حداقل یک Public IP و یک VM بعنوان واسطه کافی است و با تمرکز بر امنیت آن می‌توان امنیت بالایی برای کل VM ها برقرار کرد.در این ساختار، VM هایی که نیاز به Public IP دارند شامل Network Gateway (برای شبکه خصوصی)، Application Gateway (نقطه ورود درخواست های کاربران) و Bastion (نقطه ورود درخواست های SSH) می‌شود. این سه سرور می‌توانند سه VM مجزا با سه Public IP باشند یا اینکه یک VM با یک Public IP هر سه نقش را ایفا کند.معماری VM ها به همراه سرور های Gateway و Bastionسرور Network Gatewayهر شبکه کامپیوتری به یک Network Gateway نیاز دارد؛ چرا که ارتباط بین Node های آن شبکه و ارتباط با اینترنت از طریق آن امکان پذیر می‌شود. برای راه اندازی Network Gateway، باید یک VM با دو Interface شبکه، یکی برای دسترسی به اینترنت و دیگری برای شبکه خصوصی ایجاد کنیم.پس از ایجاد VM برای Network Gateway، باید Interface های آن را پیکره‌بندی کنیم. به عنوان مثال، در سیستم عامل Debian، با ویرایش فایل زیر می‌توان اینترفیس ها را مدیریت کرد. در این فایل، اینترفیس ens192 برای اتصال به اینترنت و ens224 برای شبکه خصوصی تعریف شده‌اند.File: /etc/network/interfaces# The loopback network interface
auto lo
iface lo inet loopback

# The public network interface
allow-hotplug ens192
iface ens192 inet static
	address 13.13.13.13/24
	gateway 13.13.13.1
        dns-nameservers 8.8.8.8 8.8.4.4

# The private network interface
auto ens224
iface ens224 inet static
        address 192.168.0.1/24
        dns-nameservers 8.8.8.8 8.8.4.4در اینترفیس ens192 از یک IP Range با آدرس 13.13.13.13/24 و Gateway با آدرس 13.13.13.1 استفاده شده که باید آنرا مطابق با IP Range و Gateway خود تغییر کنید. در اینترفیس ens224 برای شبکه خصوصی IP Range با آدرس 192.168.0.1/24 را انتخاب شده است که البته هر IP Range مجاز و آزاد برای شبکه های خصوصی را به دلخواه می‌توان وارد کرد. در انتها با دستور زیر سرویس networking را Restart کنید تا تغییرات اعمال شود.sudo systemctl restart networkingاکنون با استفاده از ابزار iptables مسیریابی شبکه خصوصی را تعریف می‌کنیم. برای این منظور، دستورات زیر را به ترتیب اجرا میکنیم.echo 1 &gt; /proc/sys/net/ipv4/ip_forward
iptables -t nat -A POSTROUTING -o ens192 -j MASQUERADE
iptables -A INPUT -i ens224 -j ACCEPT
iptables -A INPUT -i ens192 -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT -j ACCEPTتوجه کنید که تاثیر دستورات بالا بطور پیشفرض پس از Reboot شدن سرور از بین می‌روند. برای رفع این مشکل می‌توانید دستورات بالا را در یک فایل shell بریزید و آنرا بصورت یک سرویس با قابلیت Start up در بیاورید یا از ابزار iptables-persistent کمک بگیرید تا دستورات iptables را بطور دائمی ذخیره کنید.حال که سرور Network Gateway راه اندازی شد، می‌توانید از IP های آزاد در IP Range تعریف شده، یعنی 192.168.0.2 تا 192.168.0.254 برای VM های دیگر استفاده کنید تا در شبکه خصوصی ایجاد شده قرار بگیرند و به اینترنت نیز دسترسی داشته باشند.بیشتر بخوانید:https://linuxconfig.org/how-to-make-iptables-rules-persistent-after-reboothttps://tecadmin.net/run-shell-script-as-systemd-service/سرور Application Gatewayسرور Application Gateway نقطه ورود درخواست های کاربران خواهد بود. معمولا بر روی این سرور یک Web Server با قابلیت Reverse Proxy مانند NGINX نصب می‌شود که درخواست ها را دریافت و به VM های مربوطه Forward کند.برای Application Gateway می‌توانید سرور جدایی درنظر بگیرید که مانند سرور Network Gateway دارای دو Interface شبکه، یکی برای Public IP و دیگری برای Private IP (مانند 192.168.0.2) باشد و یا اینکه از همان سرور Network Gateway استفاده کنید.به عنوان مثال، فایل های زیر، کانفیگ های NGINX برای دو سرویس با دامنه های domain1.com و domain2.com هستند که درخواست های ورودی به دامنه domain1.com را به VM به آدرس 192.168.0.4 و درخواست های ورودی به دامنه domain2.com را به VM به آدرس 192.168.0.5 منتقل می‌کنند.File: /etc/nginx/sites-enabled/domain1.comserver {
    listen 80;
    server_name domain1.com;
    location / {
        proxy_pass http://192.168.0.4:80;
    }
}File: /etc/nginx/sites-enabled/domain2.comserver {
    listen 80;
    server_name domain2.com;
    location / {
        proxy_pass http://192.168.0.5:80;
    }
}بیشتر بخوانید:https://www.linode.com/docs/guides/use-nginx-reverse-proxy/سرور Bastionامکان اتصال به VM ها از طریق SSH، نیازمند دسترسی از اینترنت به آنهاست. سرور های Network Gateway و Application Gateway به دلیل داشتن Public IP در این خصوص مشکلی ندارند اما بقیه VM ها تنها یک Private IP خواهند داشت و خارج از شبکه خصوصی در دسترس نخواهند بود. برای حل این مشکل به یک سرور مجهز به Public IP به نام سرور Bastion نیاز داریم. این سرور نقش واسطه SSH را ایفا می‌کند تا بتوان خارج از شبکه خصوصی به VM های Private درون شبکه خصوصی دسترسی داشت.سرور Bastion مانند Application Gateway می‌تواند جدا یا همان سرور Network Gateway باشد. در صورت جدا بودن باید یک VM جدید با دو Interface، یکی برای Public IP و دیگری برای Private IP (مانند 192.168.0.3) ایجاد کرد.برای راه‌اندازی سرور Bastion ابتدا با دستور زیر یک کاربر جدید (مثلا با نام bastion) ایجاد کنید.sudo useradd -s /sbin/nologin bastionدستور بالا یک کاربر بدون دسترسی به Shell ایجاد می‌کند. عدم دسترسی به Shell باعث می‌شود کاربر نتواند به محتویات سرور bastion دسترسی داشته باشه چرا که این سرور قرار است تنها یک واسطه (پروکسی) برای اتصال به دیگر VM ها باشد.در گام بعدی، کلید عمومی SSH کاربران مجاز را به فایل زیر در سرور bastion اضافه کنید:/home/bastion/.ssh/authorized_keysهمچنین همان کلید را به فایل authorized_keys در VM های مربوطه نیز اضافه کنید.کاربران برای دسترسی به VM های Private در شبکه خصوصی، مثلا VM4 یا VM5 با آدرس های 192.168.0.4 و 192.168.0.5، از طریق سرور Bastion با آدرس 13.13.13.13 باید قطعه کانفیگ زیر را به فایل SSH Config در کامپیوتر شخصی خود اضافه کنند.SSH Config in MacOS: /Users/{username}/.ssh/configSSH Config in Linux: /home/{username}/.ssh/configSSH Config in Windows: C:\Users\{username}\.ssh\configHost bastion
    User bastion
    Port 22
    HostName 13.13.13.13

Host vm4
     User root
     ProxyCommand ssh bastion -W 192.168.0.4:%p

Host vm5
    User root
    ProxyCommand ssh bastion -W 192.168.0.5:%pپیکره‌بندی بالا بعنوان SSH Config، ابتدا هاست bastion به آدرس 13.13.13.13 و پورت 22 را تعریف می‌کند. در ادامه هاست های vm4 و vm5 را با آدرس های 192.168.0.4 و 192.168.0.5 تعریف می‌کند که اتصال آنها از طریق هاست تعریف شده bastion و کاربر پیشفرض root خواهد بود.اکنون به عنوان مثال، با دستورات زیر در کامپیوتر شخصی خود می‌توانید به vm5 متصل شوید:# login using default port (22) as root user
ssh vm5

# login using another port as root user
ssh vm5 -p 666

# login using default port (22) as another user
ssh milad@vm5

# login using another port as another user
ssh milad@vm5 -p 666راه اندازی VM های Privateبرای ایجاد VM های دیگر تنها یک Interface برای Private IP کافی است. فایل زیر مثالی از پیکره‌بندی Interface برای یک VM خصوصی مانند vm5 است.File: /etc/network/interfaces# The loopback network interface
auto lo
iface lo inet loopback

# The private network interface
auto ens224
iface ens224 inet static
        address 192.168.0.5/24
        dns-nameservers 8.8.8.8 8.8.4.4سخن پایانیدر این پست یک معماری مرسوم برای VM های یک سرور Bare-metal (اختصاصی) شرح داده شد. هدف از این معماری، استفاده حداقلی از Public IP ها، انعطاف پذیری و تمرکز بر روی امنیت VM ها است. معماری شرح داده شده یک معماری پایه است و معماری های خاص متناسب با سرویس مورد نظر بر روی آن ایجاد می‌شود.</description>
                <category>میلاد رحیمی</category>
                <author>میلاد رحیمی</author>
                <pubDate>Wed, 08 Jun 2022 14:32:40 +0430</pubDate>
            </item>
                    <item>
                <title>آموزش استفاده از GitHub Packages بعنوان Docker Image Registry</title>
                <link>https://virgool.io/Rocket/%D8%A2%D9%85%D9%88%D8%B2%D8%B4-%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87-%D8%A7%D8%B2-github-packages-%D8%A8%D8%B9%D9%86%D9%88%D8%A7%D9%86-docker-image-registry-ezxcica7wvcx</link>
                <description>سرویس GitHub Packages یک مخزن برای نگهداری پکیج ها و Image های داکر (Docker) است. در این پست می‌خواهیم نحوه استفاده از این سرویس به عنوان Image Registry برای Image های داکر را توضیح دهیم. این سرویس می‌تواند همانند Image Registry اصلی داکر یعنی Docker Hub مخزنی برای نگهداری Image های Docker به کاربران و سازمان (Organization) ها ارائه کند. نکته مثبتی که این سرویس می‌تواند برای کاربران ایرانی داشته باشد عدم تحریم کاربران ایرانی از طرف GitHub می‌باشد.آموزش استفاده از GitHub Packages بعنوان Docker Image Registryوزش استفاده از GitHuفرایند Authenticationبرای Pull یا Push کردن Image ها در GitHub Packages لازم است که از طریق کلاینت Docker لاگین کنید. لاگین با استفاده از Username گیتهاب و یک توکن (Personal access token) انجام میشود. برای دریافت Personal access token، در منوی کاربری سایت GitHub، مسیر زیر را دنبال کنید:Settings &gt; Developer Settings &gt; Personal access tokensدر صفحه باز شده بر روی دکمه Generate new token کلیک کنید و یک عنوان دلخواه وارد کنید، دسترسی های Read و Write را تیک بزنید و عمر توکن را مشخص کنید تا توکن را دریافت کنید.اکنون می‌توانید با دستور زیر لاگین کنید. پس از اجرای دستور می‌بایست Username گیتهاب خود و سپس توکن دریافت شده را به جای Password وارد کنید.docker login ghcr.ioساخت Image های Dockerایمیج های داکر معمولا از روی Dockerfile ها ساخته می‌شوند و یا اینکه از Image Registry های دیگر مانند Docker Hub دریافت (Pull) می‌شوند.برای ساخت یک ایمیج از یک Dockerfile می‌توانید دستور زیر اجرا کنید:docker build -t my-image-name &lt;Dockerfile-path&gt;همچنین برای Pull کردن یک ایمیج (مثلا NGINX) از Docker Hub می‌توانید دستور زیر اجرا کنید:docker pull nginx:1.21.1-alpineانتشار (Push) Image ها در Github Packagesبا دستور docker images می‌توانید لیست ایمیج های موجود در دسکتاپ یا سرور خود را مشاهده کنید. آنرا اجرا و از وجود ایمیج مورد نظر اطمینان حاصل کنید.root@example ~$ docker images
nginx  1.21.1-alpine b9e2356ea1be  10 months ago  22.8MB
ubuntu 18.04 39a8cfeef173  10 months ago  63.1MB
mysql  8.0.25  5c62e459e087  11 months ago  556MBبرای مثال می‌خواهیم ایمیج nginx را از لیست ایمیج های موجود در سرور را به GitHub Packages آپلود (Push) می‌کنیم. برای این کار ابتدا با دستور زیر یک تگ جدید با پیشوند آدرس سرویس GitHub Packages برای ایمیج مورد نظر می‌سازیم.docker tag b9e2356ea1be ghcr.io/{username}/nginx:1.21.1-alpineدر دستور بالا «b9e2356ea1be» شناسه (ID) ایمیج NGINX است که از اجرای دستور docker images بدست آوردیم. عبارت ghcr.io/{username}/nginx:1.21.1-alpine آدرس جدید ایمیج است که باید با ghcr.io (آدرس سرویس GitHub Packages) شروع شود. {username} را باید با Username یا Organization گیتهاب خود تغییر دهید. nginx نام ایمیج و 1.21.1-alpine تگ آن است.در انتها با دستور زیر، Image در GitHub Packages اپلود (Push) می‌شود. docker push ghcr.io/{username}/nginx:1.21.1-alpineلیست Images های Push شده می‌توانید در یکی از آدرس های زیر (اولی برای اکانت شخصی و دومی برای Organization) مشاهده کنید.https://github.com/{username}?tab=packageshttps://github.com/orgs/{name}/packagesتنظیمات Image هادر پنل GitHub Packages روی Image مورد نظر کلیک کنید و از ستون سمت راست بر روی دکمه Package Settings کلیک کنید. در صفحه باز شده می‌توانید تنظیمات مربوط به Image را تغییر دهید.برای مثال، در بخش Manage access می‌توانید کاربرانی را که به Image دسترسی دارند را مدیریت کنید. در صورتی که می‌خواهید Image بصورت Public ارائه شود تا برای عموم قابل استفاده باشد، بر روی دکمه Change Visibility کلیک کنید و آنرا روی Public بگذارید.دریافت (Pull) ایمیج هاهمانند Docker Hub و دیگر Docker Image Registry ها، با دستوری مشابه دستور زیر می‌توانید یک Image را بر روی دسکتاپ یا سرور خود Pull کنید.docker pull ghcr.io/{username}/nginx:1.21.1-alpineسخن پایانیدر این پست، نحوه استفاده از GitHub Packages بعنوان یک Docker Image Registry برای Pull و Push کردن Image های Docker آموزش داده شد. این سرویس می‌تواند جایگزین مناسبی برای سرویس Docker Hub که کاربران ایرانی را تحریم کرده باشد.این سرویس می‌تواند نقش یک Registry رایگان را برای Image های عمومی و خصوصی پروژه های شما ایفا کند. همچنین اگر امکان نصب پروکسی بر روی سرور را ندارید می‌توانید Image های مورد نیاز از Docker Hub را روی کامپیوتر دسکتاپ (که پروکسی دارد) Pull و در Packages گیتهاب Push کنید و در پروژه های خود از آن استفاده کنید.</description>
                <category>میلاد رحیمی</category>
                <author>میلاد رحیمی</author>
                <pubDate>Mon, 30 May 2022 14:55:19 +0430</pubDate>
            </item>
                    <item>
                <title>آموزش Deploy با استفاده از Github Actions</title>
                <link>https://virgool.io/@miladrahimi/%D8%A2%D9%85%D9%88%D8%B2%D8%B4-deploy-%D8%A8%D8%A7-%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87-%D8%A7%D8%B2-github-actions-ameeh1twkun7</link>
                <description>سرویس GitHub (گیتهاب) در چند سال اخیر امکانات جدیدی در اختیار کاربران خود فراهم کرده و در کنار آن شرایط بی نظیری برای کاربران ایرانی فراهم کرده که در این پست می‌خواهیم با استفاده از تعدادی از آنها، نحوه Deploy یک پروژه (مخزن گیتهاب) را روی سرور های خصوصی را توضیح دهیم.در خصوص ریسک استفاده از GitHub برای کار های تجاری، لازم به ذکر است که گیتهاب محدودیت های مربوط به تحریم های آمریکا را بصورت قانونی رفع کرده و شما بعنوان یک شهروند ایرانی قادر به استفاده از تمامی امکانات رایگان و Premium گیتهاب می‌باشید.پیش از ورود به بحث اصلی لازم به ذکر است که اگر Source پروژه شما خارج از GitHub نگهداری می‌شود، ابتدا آنرا به یک مخزن (Repository) در GitHub (عمومی یا خصوصی) منتقل کنید.آموزش استفاده از GitHub Actions برای Deployساخت کلید SSH برای پروژهدر سرور مورد نظر که می‌خواهید پروژه (مخزن) روی آن Deploy شود یک جفت-کلید SSH اختصاصی برای پروژه تعریف کنید. برای تعریف آن می‌توانید دستورات زیر را وارد کنید.cd ~/.ssh
ssh-keygen -t ed25519 -C my-project@my-company.comتوجه داشته باشید که نیازی به وارد کردن یک ایمیل واقعی در دستور فوق نیست و بهتر است به همین فرمت که ذکر شده، آنرا وارد کنید. پس از اجرای دستورات بالا، باید نام کلید را وارد کنید که بهتر است نام پروژه (مخزن) باشد؛ چرا که هر کلید تنها برای یک پروژه (مخزن) قابل استفاده است.Generating public/private ed25519 key pair.
Enter file in which to save the key (/root/.ssh/id_ed25519): my-projectپس از وارد کردن نام و فشردن Enter، از شما خواسته می‌شود که یک passphrase برای کلید وارد کنید که در اینجا باید آنرا خالی بگذارید و دوبار Enter بزنید؛ چرا که passphrase برای کلید های Deploy توسط گیتهاب پشتیبانی نمی‌شود. در انتها یک جفت کلید با نام های my-project (کلید خصوصی) و my-project.pub (کلید عمومی) ساخته می‌شود. اگر کلید ها را خارج از پوشه ssh. ساخته‌اید آنها به این پوشه منتقل کنید.محتوای کلید عمومی (my-project.pub) را به فایل authorized_keys در پوشه ssh. اضافه کنید؛ چرا که در ادامه گیتهاب با استفاده از کلید خصوصی مربوطه به سرور شما وصل خواهد شد تا دستورات Shell مربوط به Deploy پروژه را اجرا کند.چنانچه سرور مورد نظر در یک شبکه خصوصی قرار دارد و تنها از طریق سرور پروکسی (Bastion) قابل دسترسی است، لازم است که محتوای کلید عمومی را باید به authorized_keys در پوشه ssh. سرور Bastion نیز اضافه کنید.اگر فایل config در پوشه ssh. وجود ندارد آنرا بسازید سپس بخش زیر را به آن اضافه کنید.Host github.com-my-project
    Hostname github.com
    IdentityFile=/root/.ssh/my-projectآدرس کلید خصوصی (IdentityFile) را در کانفیگ بالا متناسب با مسیر‌ آن در سرور تغییر دهید. کانفیگ فوق باعث می‌شود که ابزار Git برای Clone و Pull کردن پروژه مورد نظر از کلید اختصاصی پروژه که در مرحله قبل ساخته‌اید استفاده کند.فرایند Clone کردن Repository در سروربرای Clone کردن مخزن در سرور ابتدا باید کلید عمومی ساخته شده در مراحل قبل را به Deploy keys مخزن در گیتهاب اضافه کنید. برای این کار از سربرگ Setting مخزن در گیتهاب بر روی گزینه Deploy keys کلیک کنید و در صفحه Load شده بر روی دکمه Add deploy key کلیک کنید و کلید عمومی (my-project.pub) را به آن اضافه کنید. می‌توانید عنوانی برای کلید وارد کنید یا آنرا خالی رها کنید تا ایمیل انتهای کلید برای عنوان در نظر گرفته شود. اگر گزینه Allow write access را تیک بزنید، اجازه تغییر و Push کردن به سرور داده می‌شود و در غیراینصورت سرور تنها می‌تواند پروژه را Clone و Pull کند.اکنون می‌توانید در سرور خود با دستور زیر مخزن را Clone کنید.git clone git@github.com-my-project:company/my-project.gitتوجه کنید که پس از کپی کردن آدرس مخزن از گیتهاب، باید هاست github.com را باgithub.com-my-project (مطابق با محتوای فایل config که در مراحل قبل شرح داده شد) جایگزین کنید تا طبق کافیگ SSH از کلید اختصاصی پروژه برای Clone و Pull (Deploy) استفاده شود.راه اندازی GitHub Actionsابزار GitHub Actions همانند CI/CD در Gitlab برای ساخت Pipeline های CI/CD استفاده می‌شود. با ساخت فایل Action که در ادامه شرح داده می‌شود، می‌توانید مخزن پروژه را به یک فرایند Deploy خودکار مجهز کنید تا با هر Push روی Branch اصلی (master)، بصورت خودکار پروژه روی سرور Deploy شود.پیش از ساخت فایل Action ابتدا محتوای کلید خصوصی را که در مراحل قبل ایجاد کردید را به عنوان متغیر Secret در مخزن تعریف کنید. برای اینکار در سربرگ Setting مخزن، بر روی گزینه Actions از منوی Secrets کلیک کنید. در صفحه باز شده متغیری به نام SSH_PRIVATE_KEY و با محتوای کلید خصوصی (my-project) تعریف کنید. مطمئن شوید که در انتهای کلید یک خط خالی وجود داشته باشد.اکنون می‌توانید فایل Action را در مسیر زیر در دایرکتوری پروژه ایجاد کنید:.github/workflows/cd.ymlچنانچه پوشه های github. و workflows وجود ندارند آنها را بسازید و سپس فایل cd.yml را با محتوای زیر در آن مسیر ایجاد کنید.name: CD

on:
  push:
    branches: [ master ]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - name: Deploy
      uses: appleboy/ssh-action@master
      with:
        host: 10.11.12.13
        port: 22
        username: root
        key: ${{ secrets.SSH_PRIVATE_KEY }}
        script: |
          cd /path/to/my-project
          git reset --hard HEAD^
          git pullمطابق با host (ip) سرور و فرایند Deploy پروژه، فایل بالا را ویرایش کنید.چنانچه سرور مورد نظر در یک شبکه خصوصی قرار دارد و تنها از طریق سرور پروکسی (Bastion) قابل دسترسی است، به جای محتوای بالا برای cd.yml از محتوای زیر استفاده کنید:name: CD
  on:
   push:
     branches: [ master ]
  jobs:
   build:
     runs-on: ubuntu-latest
     steps:
     - name: Deploy
       uses: appleboy/ssh-action@master
       with:
         host: 192.168.0.2
         port: 22
         username: root
         key: ${{ secrets.SSH_PRIVATE_KEY }}
         proxy_host: 10.11.12.13
         proxy_port: 22
         proxy_username: bastion
         proxy_key: ${{ secrets.SSH_PRIVATE_KEY }}
         script: |
           cd /path/to/my-project
           git reset --hard HEAD^
           git pull
فایل cd.yml بالا مشابه فایل قبلی است با این تفاوت که اطلاعات سرور پروکسی (Bastion) به آن اضافه شده است.در انتها تغییرات پروژه که شامل ایجاد فایل Action پروژه می‌باشد را Commit و Push کنید. پس از Push شدن تغییرات روی برنچ master، گیتهاب Action ایجاد شده را بصورت خودکار اجرا می‌کند. نتایج اجرای Actions را در سربرگ Actions در صفحه مخزن پروژه می‌توانید مشاهده کنید.کلید های Deploy و SSH Loginدر فرایند Deploy شرح داده شده، یک جفت-کلید SSH اختصاصی برای پروژه ایجاد کردیم و از کلید عمومی آن برای Clone یا Deploy کردن و از کلید خصوصی آن برای SSH Login استفاده کردیم. اما در صورتی که تمایل داشته باشید می‌توانید از کلید های متفاوتی برای این دو منظور استفاده کنید. برای مثال می‌توانید یک کلید خصوصی جهت دسترسی به سرور را برای همه پروژه ها ایجاد و آنرا بعنوان متغیر Secret در همه مخزن های مربوطه تعریف کنید. با این وجود، کلید Deploy را نمی‌توانید به صورت اشتراکی برای دو Repository استفاده کنید و این کلیدها باید منحصر بفرد باشند.سخن پایانیبا توجه به رفع قانونی محدودیت های GitHub برای کاربران ایرانی، می‌توانید از Private Repository های گیتهاب جهت نگهداری و Deploy پروژه های تجاری استفاده کنید و هزینه های مربوط به Setup، پیکره‌بندی و نگهداری Self-hosted Gitlab را متحمل نشوید. در این آموزش نیز نحوه یک دپلوی ساده (Git Pull) با استفاده از ابزار GitHub Actions شرح داده شد تا بهتر با این ابزار جذاب و بی دردسر آشنا شوید.</description>
                <category>میلاد رحیمی</category>
                <author>میلاد رحیمی</author>
                <pubDate>Sun, 27 Feb 2022 13:50:21 +0330</pubDate>
            </item>
                    <item>
                <title>آموزش Laravel Octane و Swoole/RoadRunner</title>
                <link>https://virgool.io/laravel-community/%D9%85%D8%B9%D8%B1%D9%81%DB%8C-laravel-octane-%D9%88-%D9%86%D8%B3%D9%84-%D8%AC%D8%AF%DB%8C%D8%AF-%D9%BE%D8%B1%D9%88%DA%98%D9%87-%D9%87%D8%A7%DB%8C-%D9%84%D8%A7%D8%B1%D8%A7%D9%88%D9%84-ban81lsz5dsv</link>
                <description>پکیج Laravel Octane یکی از ابزار های جدید معرفی شده توسط تیم Laravel است که می‌تواند بطور چشمگیری سرعت اپلیکیشن های ساخته شده با فریم ورک لاراول را بالا ببرد. این ابزار برای ارائه چنین عملکرد فوق العاده‌ای از اپلیکیشن سرور RoadRunner یا افزونه Swoole استفاده می‌کند که در این پست شرح داده می‌شوند.مستندات رسمی لاراول درباره Laravel Octane را می‌توانید از لینک زیر بخوانید.https://laravel.com/docs/master/octaneپکیج Laravel Octaneلاراول بدون Octaneابتدا Lifecycle یا چرخه اجرای فریم ورک لاراول را بدون Octane را بررسی کنیم. این چرخه بصورت خلاصه به شکل زیر است:User Request -&gt; Web Server -&gt; PHP-FPM -&gt; PHP files -&gt; Outputدر این حالت لاراول حتما به یک وب سرور مانند NGINX یا Apache HTTP Server نیاز دارد. درخواست های  کاربران از طریق وب سرور دریافت می‌شود و از آنجا به PHP-FPM ارسال می‌شود.در این چرخه، PHP-FPM به ازی هر درخواست از سوی وب سرور، فایل های PHP را Compile، اجرا و خروجی را به وب سرور بازمی‌گرداند.مشکل این چرخه، Compile و اجرای فایل های PHP به ازای هر درخواست کاربر است. به این صورت حجم زیادی از پردازش های تکراری انجام می‌شود و منابعی که می‌توان مورد استفاده مجدد قرار بگیرند (مانند Connection به پایگاه داده) آزاد و دوباره اشغال می‌شوند.متاسفانه راهکار رسمی از طرف PHP برای حل این مشکل فعلا (نسخه ۸) در دسترسی نیست و این مشکل باعث کاهش شدید محبوبیت این زبان و مهاجرت شرکت های بزرگ به زبان ها و تکنولوژی های دیگر شده است.با این وجود، جامعه PHP ابزار هایی مانند افزونه Swoole و اپلیکیشن سرور RoadRunner را ارائه کرده‌اند که می‌تواند سرعت اجرای پروژه های PHP را بطور چشمگیری بالا ببرد و بر مشکلات ذکر شده غلبه کند. در همین راستا، فریم‌ورک Laravel پکیج Laravel Octane را که از ابزار های فوق استفاده می‌کند را معرفی کرده است.پکیج Laravel Octaneهمانطور که قبلا اشاره شد، پکیج Laravel Octane برای بهینه سازی پروژه های لاراول و افزایش سرعت آنها توسط تیم لاراول ارائه شده است. این پکیج برای رسیدن به چنین عملکردی از یکی از ابزار های Swoole یا RoadRunner به دلخواه کاربر (بعنوان Driver) استفاده می‌کند. در این پست کوتاه درباره RoadRunner و سپس در مورد Swoole (روش پیشنهادی نویسنده) مفصل تر توضیح داده ‌می‌شود.اپلیکیشن سرور RoadRunnerابزار RoadRunner یک اپلیکیشن سرور، Reverse Proxy و Load Balancer برای پروژه های PHP است. این ابزار با زبان برنامه نویسی Go نوشته شده و از قابلیت های همزمانی (Concurrency) آن (Goroutine ها) استفاده می‌کند تا بر مشکل ذکر شده غلبه کند.با استفاده از RoadRunner پروژه PHP تنها یکبار Compile و اجرا می‌شود. پس اجرا شدن پروژه ارتباطی از طریق Socket بین پروژه و RoadRunner برقرار می‌شود. به ازای هر درخواست کاربر یک Goroutine (مشابه Thread اما سبک‌تر) در RoadRunner ایجاد می‌شود و در آن Goroutine درخواست به اپلیکیشن PHP ارسال می‌شود و در اپلیکیشن یک تابع (Controller) اجرا و پاسخ به Goroutine و از آنجا به کاربر نهایی بازگردانده می‌شود.بطور خلاصه می‌توان چرخه اجرای اپلیکیشن PHP با استفاده از RoadRunner را به صورت زیر در نظر گرفت.User Request -&gt; RoadRunner -&gt; PHP function (controller) -&gt; Outputبا وجود RoadRunner دیگر نیازی به NGINX نیست و RoadRunner خود نقش وب سرور را نیز ایفا می‌کند.افزونه Swooleیکی از تلاش های Community زبان PHP برای حل مشکلات ذکر شده و همچنین عدم وجود قابلیت های همزمانی Extension یا افزونه Swoole است که با زبان C پیاده سازی شده است. این افزونه قابلیت های همزمانی (Coroutine ها) و یک سری ابزار مفید مانند HTTP Handler، وب سوکت، MQTT Server و ... را به PHP اضافه می‌کند.قابلیت HTTP Handler مهمترین قابلیت این افزونه و قابلیت مورد استفاده Laravel Octane است. با استفاده از این قابلیت، خود PHP می‌تواند درخواست های کاربر را دریافت کند و دیگر به نیازی به وب سرور نیست. نمونه کد زیر به PHP خام نوشته شده و مثالی برای استفاده از Swoole در PHP است.&lt;?php

use Swoole\Http\Server;
use Swoole\Http\Request;
use Swoole\Http\Response;

$server = new Swoole\HTTP\Server(&amp;quot127.0.0.1&amp;quot, 8080);

// تنها یکبار بهنگام اجرای اپلیکیشن فراخوانی می‌شود
$server-&gt;on(&amp;quotStart&amp;quot, function(Server $server)
{
    echo &amp;quotSwoole http server is started at http://127.0.0.1:8080\n&amp;quot
});

// به ازای هر درخواست کاربر فراخوانی می‌شود
$server-&gt;on(&amp;quotRequest&amp;quot, function(Request $request, Response $response)
{
    $response-&gt;header(&amp;quotContent-Type&amp;quot, &amp;quottext/html&amp;quot);
    $response-&gt;end(&amp;quot&lt;p&gt;Hello World&lt;/p&gt;&amp;quot);
});

$server-&gt;start();کد بالا بدون نیاز به هیچ وب سروری با دستور زیر قابل اجرا است.php index.phpبا دستور فوق، فایل PHP تنها یکبار Compile و اجرا می‌شود. به ازای هر درخواست از سوی کاربر، افزونه Swoole در PHP یک Coroutine (مشابه Goroutine ها در زبان Go) ایجاد و تابع مربوط (در کد بالا) را فراخوانی و جواب تابع (Hello World) به کاربر بازگردانده می‌شود.بطور خلاصه چرخه اجرای پروژه با استفاده از HTTP Handler افزونه Swoole بصورت زیر است.User Request -&gt; PHP function (controller) -&gt; Outputاین چرخه مشابه چرخه‌ی اجرا در زبان Go و تکنولوژی Node.js است و همان چرخه‌ای است که از یک زبان امروزی انتظار داریم.اجرای لاراول با Octaneدر این بخش نحوه اجرای پروژه های مبتنی بر فریم ورک لاراول با استفاده از پکیج Laravel Octane و Docker را توضیح می‌دهیم. اگر با روش اجرای لاراول با داکر و داکر کمپوز آشنا نیستید می‌توانید پست توسعه و اجرای پروژه های لاراول با داکر و داکر-کمپوز را بخوانید.در لینک زیر فایل docker-compose.yml و دیگر فایل های مورد نیاز برای اجرای لاراول با استفاده از Laravel Octane آماده شده است. آنرا دانلود و به پروژه خود اضافه کنید.https://github.com/miladrahimi/laravel-docker-compose/tree/main/php-8.0-octaneدر فایل docker-compose.yml موجود در لینک بالا، دیگر خبری از کانتینر NGINX نیست و Port اپلیکیشن همان Port کانتینر PHP خواهد بود که می‌توانید در فایل .env پروژه با نام PHP_EXPOSED_PORT ست کنید. اگر Dockerfile مربوط به PHP را هم بررسی کنید نحوه نصب افزونه Swoole را می‌بینید.پس از ساخت فایل .env متغیر OCTANE_SERVER را با مقدار &quot;swoole&quot; به آن اضافه کنید و دستورات زیر را برای اجرای لاراول انجام دهید.docker-compose build
// دانلود و ساخت ایمیج های داکر

docker run --rm -it --volume $(pwd):/app sample_php composer install
// نصب پکیج ها با استفاده از کمپوزر درون ایمیج پروژه

docker run --rm -it --volume $(pwd):/app sample_php composer require laravel/octane
// نصب پکیج لاراول اکتان

docker run --rm -it --volume $(pwd):/app sample_php php artisan key:generate
// ساخت کلید امنیتی پروژه

docker-compose up -d
// اجرای پروژه با داکر 

docker-compose ps
// نمایش پورت های اکسپوز شدهنحوه اجرا شدن لاراول با Laravel Octaneبا اجرا شدن پروژه، یک Object از کلاس Application لاراول (app$) ساخته می‌شود. یکبار همه Service Provider های لاراول register و boot می‌شود و لاراول (app$) آماده پاسخگویی به درخواست های کاربر می‌شود.پس از دریافت درخواست کاربر لاراول یک clone از object اپلیکیشن (app$) ایجاد می‌کند و درخواست را به آن می‌دهد و خروجی را از آن دریافت می‌کند. User Request -&gt; Laravel -&gt; clone $app object -&gt; router -&gt; controller -&gt; ...به این صورت مراحل ایجاد object اپلیکیشن و راه اندازی لاراول تنها یکبار صورت می‌گیرد و در ادامه با درخواست کاربر مستقیما Router و Controller مربوطه اجرا و پاسخ به کاربر باز می‌گردد.اجرای لاراول با استفاده از Laravel Octane حدود ۱۰ برابر سریع تر از اجرای آن با PHP-FPM است. البته لازم به ذکر است این ضریب حدودی است و مقدار دقیق آن کاملا وابسته به کد های پروژه می‌باشد.چالش های Laravel Octaneدر انتها باید گفت اگر سرعت چشمگیر Laravel Octane شما را مجذوب کرده اما باید مراقب عادات همیشگی خود در PHP باشید! بخاطر داشته باشید که بسیاری از قسمت های لاراول در طول سرویس دهی تنها یکبار اجرا می‌شوند.از مواردی مانند تابع ()auth و ()request که مختص به درخواست است در Service Provider ها که تنها یکبار اجرا می‌شوند استفاده نکنید.مراقب Property های static در کلاس های پروژه باشید. مقدار آنها برای درخواست های کاربران بعدی نیز باقی می‌ماند و ممکن است از لحاظ امنیتی و عملکردی مشکل ساز شوند. اگر این متغیر ها آرایه باشند، علاوه بر آن می‌توانند باعث Memory Leak (نشت حافظه)‌ شوند. به این صورت که آنقدر بزرگ شوند که کل RAM سرور را پر کنند و سرور از سرویس‌دهی خارج شود.مثال زیر از مستندات رسمی Laravel را در نظر بگیرید.class UsersController {
    public function index()
    {
        Service::$data[] = Str::random(10);
        // ...
    }
}هر بار با درخواست کاربر اکشن index از کنترلر UsersController اجرا می‌شود و یک مقدار تصادفی به آرایه data از کلاس Service اضافه می‌شود. در چرخه لاراول بدون Octane به دلیل اینکه همه چیز از اول کامپایل و اجرا می‌شد، مثال بالا هیچ خطری نداشت. اما اکنون پروژه تنها یکبار کامپایل و اجرا می‌شود و آرایه data برای درخواست های بعدی هم باقی می‌ماند و علاوه بر خطر امنیتی، به ازای هر درخواست یک آیتم جدید به آن اضافه و سنگین تر می‌شود و پس از تعدادی درخواست RAM سرور را بطور کامل اشغال می‌کند.قابلیت های Swoole و Laravel Octaneدر این بخش قابلیت هایی از پکیج Laravel Octane را معرفی می‌کنیم که تنها با درایور Swoole در دسترس هستند و درایور RoadRunner قادر به فراهم کردن آنها نیست. این قابلیت به شرح زیر هستند و هر کدام به بخش مربوطه در مستندات رسمی لاراول لینک شده اند.اجرای همزمان توابع: با استفاده از این قابلیت می‌توانید چند تابع که کار های سنگین  مانند کار با فایل و فراخوانی API را با همزمان فراخوانی کنید و به محض پایان یافتن همه آنها آرایه‌ای از نتایج بازگردانده می‌شود.اجرای دوره‌ای توابع: با استفاده از این قابلیت می‌تواند یک تابع را بصورت دوره‌ای (برای مثال هر ۵ دقیقه یکبار) اجرا کنید. این قابلیت می‌تواند جایگزین Scheduled Tasks باشد.درایور Cache: از این پس به جای Redis یا فایل‌ها می‌توانید از درایور octane برای Cache استفاده کنید.قابلیت های آیندهافزونه Swoole قابلیت های بسیار کاربردی و مفیدی بخصوص در زمینه همزمانی برای PHP فراهم می‌کند و تعدادی از آنها مورد استقبال پکیج Laravel Octane قرار گرفته است. با این وجود، متاسفانه پکیج Octane قابلیت بسیار مهم Coroutine های Swoole را برای کاربران غیرفعال کرده که امیدواریم در آینده آنها را نیز فعال کند تا باز هم برنامه نویس های PHP را به نسل جدیدتری هدایت کند.قابلیت Coroutine های افزونه Swoole همانند Goroutine ها در زبان Go به برنامه نویس ها امکان ایجاد Thread های سبک سمت User را فراهم ‌می‌کند. با این قابلیت، می‌توان بدون نیاز به Job های پیچیده لاراول، بسیاری از کار ها بصورت async انجام داد.این قابلیت از سوی Laravel Octane بصورت پیشفرض غیرفعال شده و برنامه نویس ها بصورت پیشفرض نمی‌توانند از آن استفاده کنند. اما به احتمال زیاد، تیم لاراول در نسخه های بعدی Facade ها و API هایی جهت کار با آنها را پیاده سازی خواهد کرد.سخن پایانیدر این مقاله، پکیج Laravel Octane معرفی شد. امکاناتی که این پکیج در اختیار لاراول قرار می‌دهد در دو بخش، یکی افزایش سرعت پاسخگویی که با هر دو درایور Swoole و RoadRunner قابل اجرا بود و دیگر امکاناتی نظیر همزمانی، Cache و اجرای دوره‌ای بود که تنها درایور Swoole ارائه می‌کرد.در Benchmark های موجود در اینترنت این افزایش سرعت حدود ۱۰ برابر برای فراخوانی یک API ساده از اپلیکیشن تخمین زده شده است. اما بسته به پروژه و بهینه بودن آن این افزایش سرعت می‌تواند بیشتر یا کمتر باشد.اجرای لاراول با استفاده از Laravel Octane می‌تواند یکی از مواردی باشد که در پروژه بعدی خود در نظر بگیرید و در صورتی که تجربه‌ای در این زمینه دارید لطفا در دیدگاه های این پست بنویسید.</description>
                <category>میلاد رحیمی</category>
                <author>میلاد رحیمی</author>
                <pubDate>Tue, 11 Jan 2022 16:22:11 +0330</pubDate>
            </item>
                    <item>
                <title>برنامه نویسی را از کجا شروع کنیم؟</title>
                <link>https://virgool.io/@miladrahimi/%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87-%D9%86%D9%88%DB%8C%D8%B3%DB%8C-%D8%B1%D8%A7-%D8%A7%D8%B2-%DA%A9%D8%AC%D8%A7-%D8%B4%D8%B1%D9%88%D8%B9-%DA%A9%D9%86%DB%8C%D9%85-u7jgtjnh2dih</link>
                <description>برنامه نویسی یکی از مشاغل پر تقاضای امروزی است. به همین خاطر هر روزه بر محبوبیت این شغل افزوده می‌شود. با این حال مسیر یادگیری و پیشرفت در این شغل به دلیل شاخه های متعدد آن و مفاهیم و ابزار متنوع مورد نیاز، پیچیده است. در این پست سعی داریم نگاهی کلی به این شغل و مسیر یادگیری آن داشته باشیم.برنامه نویسی چیست؟برنامه نویسی فرایند تبدیل مسائل و نیازمندی های زندگی واقعی به الگوریتم ها و نهایتا کد های برنامه نویسی قابل اجرا بر روی پردازنده کامپیوتر، موبایل و ... می‌باشد. خروجی کار برنامه نویسی می‌تواند یک نرم افزار، یک اپلیکیشن موبایل، یک اپلیکیشن وب و ... باشد.برای اطلاعات بیشتر صفحه ویکی‌پدیای برنامه نویسی ‌رایانه‌ای را بخوانید.پیشنیاز برنامه نویسی چیست؟پیشنیاز برنامه نویسی، آشنایی با کامپیوتر، اینترنت و موبایل است. یک برنامه نویس ابتدا باید یک کاربر حرفه‌ای کامپیوتر باشد، لازم است با تعدادی نرم افزار (اپلیکیشن) تجربه کار کردن داشته باشد و بهتر است تعدادی سیستم عامل همانند ویندوز، لینوکس، مک، اندروید و iOS را بررسی کرده باشد. هر چقدر مهارت شخص در استفاده از اپلیکیشن ها بیشتر باشد احتمال کسب مهارت در تولید آنها نیز بالاتر است.پیشنیاز دیگر برنامه نویسی، علاقه به ریاضیات و حل مسائل ریاضی است. لازم نیست روش حل انتگرال دوگانه در مختصات قطبی را بلد باشید؛ اما اینکه از ریاضیات فراری باشید احتمالا علاقه‌ای به برنامه نویسی هم ندارید.قدم اول در برنامه نویسی چیست؟قدم اول یادگیری الگوریتم و فلوچارت است. پس از یادگیری این مبحث شما می‌توانید مسائل واقعی را به الگوریتم و فلوچارت تبدیل کنید. الگوریتم و فلوچارت روشی برای تعریف مسائل هستند بطوری که قابلیت تبدیل شدن به کد های برنامه نویسی دارند. در واقع پس از یادگیری یک زبان برنامه نویسی در مرحله بعد، می‌توانید الگوریتم ها و فلوچارت های طراحی شده را به آن زبان برنامه نویسی بنویسید.با جستجوی عبارتی مانند کتاب الگوریتم و فلوچارت می‌توانید انواعی از کتاب های رایگان و پولی درباره این مبحث را پیدا کنید.از چه زبانی شروع کنیم؟در این باره نظرات متفاوتی وجود دارد و من هم نظر خودم را می‌نویسم!من زبان C را پیشنهاد می‌کنم. این زبان به مادر زبان های برنامه نویسی معروف است و بیشتر زبان های امروزی از این زبان الهام گرفته و یا آنرا توسعه داده اند. از ویژگی های این زبان می‌توان به موارد زیر اشاره کرد:برای انجام تمرین های مقدماتی ساده است و یادگیری آن راحت است.برنامه نویس را با مفاهیم پایه برنامه نویسی آشنا می‌کند.مشابه زبان های برنامه نویسی امروزی است.انواع دوره های آموزشی آن برای افراد کاملا مبتدی وجود دارد.در ادامه برای یادگیری مسائلی همچون شی گرایی، می‌توانید به سراغ زبان ++C بروید که در واقع نسخه توسعه داده شده C است و قابلیت های جدیدی همچون شی گرایی را به آن افزوده شده است.سایت های زیر منابع خوبی برای یادگیری این زبان برنامه نویسی هستند و بعضی از آنها محیط اجرای این زبان را نیز در اختیار شما قرار می‌دهد تا نیازی به نصب آن بر روی دستگاه خود نباشید.https://www.tutorialspoint.com/cprogramming/index.htmhttps://www.learn-c.orghttps://www.w3schools.in/c-tutorialهمنیاز های برنامه نویسیدر کنار زبان برنامه نویسی که یاد می‌گیرید، باید مباحث دیگری نیز بیاموزید. این مباحث عبارت‌اند از:ساختمان داده (نحوه ساختاردهی به داده های موجود در برنامه)https://www.tutorialspoint.com/data_structures_algorithms/index.htmالگوریتم (بررسی میزان بهینه بودن الگوریتم ها)https://www.tutorialspoint.com/data_structures_algorithms/index.htmشبکه (طرز کار شبکه های کامپیوتری و اینترنت)https://www.tutorialspoint.com/data_communication_computer_network/index.htmپایگاه داده یا Database (نحوه ذخیره سازی اطلاعات)https://www.tutorialspoint.com/dbms/index.htmمهندسی نرم افزار (فرایند های تولید نرم افزار)https://www.tutorialspoint.com/software_engineering/index.htmشاخه های برنامه نویسیپس از یادگیری حداقل یک زبان برنامه نویسی و مباحثی مانند پایگاه داده و شبکه، بهتر است شاخه های مختلف برنامه نویسی را بررسی و تست کنید و در نهایت شاخه مورد علاقه خود را انتخاب و تمام تمرکز خود را بر روی آن شاخه بگذارید. برخی از شاخه های پرکابرد امروزی در ادامه شرح داده شده اند.برنامه نویسی Androidسیستم عامل اندروید (Android) یکی از سیستم عامل های محبوب برای موبایل است. برنامه نویسی Android به معنی برنامه نویسی اپلیکیشن های موبایل قابل اجرا بر روی سیستم عامل Android می‌باشد. برنامه نویس های اندریود معمولا از زبان Java و Kotlin برای ساخت اپلیکیشن های Android استفاده می‌کنند.برنامه نویسی iOSسیستم عامل iOS ساخت شرکت Apple و بر روی iPhone و iPad نصب می‌باشد. برنامه نویسی iOS به معنی برنامه نویسی اپلیکیشن های قابل اجرا بر روی دستگاه های iPhone ،iPad و دیگر دیوایس های ساخت شرکت Apple است. برنامه نویس های iOS معمولا از زبان Swift برای ساخت اپلیکیشن های iOS استفاده می‌کنند.برنامه نویسی وبعنوان برنامه نویسی وب یک عنوان قدیمی است و امروزه عنوانی نامشخص محسوب می‌شود که بهتر است از آن استفاده نکنیم. به جای آن از عنوان های برنامه نویسی Front-end و Back-end استفاده کنیم. این دو دنیای برنامه نویسی در ادامه توضیح داده می‌شوند.برنامه نویسی Front-endبرنامه نویسی Front-end یا بطور خلاصه فرانت به معنی برنامه نویسی برای ساخت اپلیکیشن های تحت وب می‌باشد. برنامه نویس های  Front-end از زبان JavaScript (جاوا اسکریپت)‌ برای ساخت وب اپلیکیشن ها استفاده می‌کنند.برنامه نویسی Back-endبرنامه نویسی Back-end یا برنامه نویسی سمت سرور به معنی برنامه نویسی برای طراحی اپلیکیشن های قابل اجرا بر روی سرور است. اپلیکیشن سمت سرور همان برنامه ای است که اپلیکیشن موبایل و وب با آن ارتباط برقرار می‌کنند. برای مثال در سرویس اینستاگرام، اپلیکیشن موبایل اینستاگرام اطلاعات کاربر را جهت نام‌نویسی به اپلیکیشن سرور اینستاگرام ارسال می‌کند و پس از آن هر بار که اپلیکیشن موبایل اینستاگرام را باز می‌کنید، اپلیکیشن موبایل اطلاعات اینبار از اپلیکیشن سرور دریافت می‌کند و به کاربر نمایش می‌دهد.برنامه‌نویسی Back-end دنیای وسیع تری نسبت به اپلیکیشن های وب و موبایل به حساب می‌آید و زبان ها و ابزار های گوناگونی برای آن وجود دارد که معروف ترین آنها Go، جاوا، PHP، جاوا اسکریپت، #C،‌ پایتون هستند.برنامه نویسی بازیبرنامه نویسی بازی یا Game developement بخشی از فرایند طراحی بازی های رایانه‌ای است که در کنار طراحی گرافیک بازی منجر به تولید بازی های رایانه‌ای می‌شود. از محبوب ترین زبان های برنامه نویسی مورد استفاده در توسعه بازی ها می‌توان به ++C، جاوا، #C و جاوااسکریپت اشاره کرد.برای اطلاعات بیشتر صفحه ویکی‌پدیای توسعه بازی های ویدویی را بخوایند.هوش مصنوعی و یادگیری ماشینهوش مصنوعی و زیرشاخه اصلی آن یعنی یادگیری ماشین از شاخه های برنامه نویسی هستند که معمولا به کمک اپلیکیشن های Back-end و بازی ها می‌آیند. در این شاخه ها با استفاده از مفاهیم ریاضی و آمار و احتمالات الگوریتم هایی جهت شبیه سازی انسان، یادگیری، بهبود پیشنهاد ها به کاربران و ... طراحی می‌شود.برای مطالعه بیشتر صفحه ویکی‌پدیای هوش مصنوعی را بخوایند.</description>
                <category>میلاد رحیمی</category>
                <author>میلاد رحیمی</author>
                <pubDate>Fri, 17 Dec 2021 18:05:29 +0330</pubDate>
            </item>
                    <item>
                <title>کاربرد Interface ها در PHP و Laravel</title>
                <link>https://virgool.io/RubikGroup/%DA%A9%D8%A7%D8%B1%D8%A8%D8%B1%D8%AF-interface-%D9%87%D8%A7-%D8%AF%D8%B1-php-%D9%88-laravel-p0yp4a30i7mi</link>
                <description>واژه Interface به معنی رابط (کاربری) است. رابط کاربری در برنامه نویسی، رفتار (متد) های یک کلاس (ماژول) می‌باشد که دیگر ماژول ها از طریق آنها می‌توانند با آن کلاس (ماژول) ارتباط برقرار کنند.برای مثال، کلاس زیر (Gmail) مسئولیت فرستادن ایمیل را بر عهده دارد.class Gmail {
    public function send(string $to, string $content) {
         // Preparing Gmail API requirements
        $this-&gt;call([$to, $content, $username, $password, $server]);
    }
    private function call(array $parameters) {
        // Send email using the Gmail API
    }
}در کلاس بالا، متد send بصورت public (عمومی) تعریف شده و دیگر ماژول ها برای ارسال ایمیل آن را فراخوانی می‌کنند. این متد، رابط کاربری کلاس محسوب می‌شود. در طرف دیگر، متد call یک متد private (خصوصی) است و تنها مصرف داخلی دارد (متد send از آن استفاده می‌کند) و جزو رابط کاربری کلاس محسوب نمی‌شود.اکنون با استفاده از یک Interface، رابطه کاربری کلاس های ارسال ایمیل را تعریف کنیم.interface Email {
    function send(string $to, string $content);
}در کلاس Gmail نیز مشخص می‌کنیم که این کلاس از رابط کاربری Email پیروی می‌کند.class Gmail implements Email { ... }البته هنوز سوال اصلی که Interface چه کمکی به ما می‌کنند پابرجاست. این سوال را با معرفی اصول SOLID پاسخ می‌دهیم.کاربرد Interface ها در PHP و Laravelاصول SOLIDاصول SOLID، مجموعه پنج اصل مهم در برنامه نویسی شی گرا (Object-oriented programming) است. این اصول عبارت‌اند از:اصل Single-responsibility (تک مسئولیتی)اصل Open-closed (باز-بسته)اصل Liskov substitution (جایگزینی لیسکوف)اصل Interface segregation (تفکیک رابطه کاربری)اصل Dependency inversion (وارونگی وابستگی)اصل Dependency inversion در SOLIDاصل Dependency inversion (وارونگی وابستگی) در برنامه نویسی شی گرا و اصول SOLID، بر وابستگی به تعاریف انتزاعی (Abstraction) به جای وابستگی به پیاده سازی (Concrete یا Implementation) تاکید می‌کند.به بیان ساده ساده تر، ماژول های پروژه باید به Interface ها (مانند Email) وابستگی داشته باشند، نه پیاده سازی ها (مانند Gmail). پیاده سازی ها ممکن است در طول زمان تغییر کنند و فقط Interface ها هستند که ثابت می‌مانند.برای مثال، در زیر یک Controller به نام UsersContronller را می‌بینید. در متد create که Action مربوط به API ساخت کاربر جدید است، پس از ذخیره اطلاعات کاربر در دیتابیس، یک ایمیل خوشامد گویی برای او ارسال می‌کند.class UsersContronller extends Controller {
    public function create(Request $request) {
        // Save user information into database
        $email = new Gmail();
        $email-&gt;send($user-&gt;email, &#039;Welcome dear user...&#039;);
    }
}مشکل Controller بالا تا وقتی که ما تنها از Gmail برای ارسال ایمیل استفاده می‌کنیم ممکن است مشخص نشود. وقتی تصمیم بگیریم از سرویس ایمیل دیگری همچون Mailgun استفاده کنیم، باید این کلاس و دیگر کلاس هایی که از Gmail استفاده می‌کنند را پیدا کرده و کد های آنها را تغییر دهیم.مشکل Controller بالا وابستگی به پیاده سازی (به جای وابستگی به تعاریف انتزاعی) است و اصل Dependency inversion از اصول SOLID را نقض کرده است. برای رفع این مشکل، این Controller را بصورت زیر بازنویسی می‌کنیم.class UsersContronller extends Controller {
    public function create(Request $request, Email $email) {
        // Save user information into database
        $email-&gt;send($user-&gt;email, &#039;Welcome dear user...&#039;);
    }
}دیگر بخش های پروژه را نیز در کد زیر می‌بینید.interface Email {
    function send(string $to, string $content);
}
class Gmail implements Email { ... }
class Mailgun implements Email { ... }از Interface ها نمی‌توان Object (شی) ساخت، اما از کلاس هایی که Interface ها پیاده سازی می‌کنند می‌شود Object ساخت. نوع پارامتر email در متد create کنترلر بالا، اینترفیس Email است. در نتیجه این پارامتر می‌تواند یک Object از کلاسی مانند Gmail یا Mailgun باشد که اینترفیس Email را پیاده سازی می‌کند. هر کلاسی که از رابط کاربری اینترفیس Email پیروی کند مجبور می‌شود متد send را پیاده سازی کند. در نتیجه هر Object که از نوع اینترفیس Email باشد حتما دارای متد پیاده سازی شده‌ی send است.کلاس UsersContronller اکنون وابسته به اینترفیس Email (یک تعریف انتزاعی) است و وابستگی به پیاده سازی هایی همچون Gmail یا Mailgun ندارد. برای استفاده از این کلاس می‌توانید هر پیاده سازی که از رابط کاربری Email پیروی کند را به متد create آن تزریق کنیم. تزریق این وابستگی می‌تواند توسط ابزاری به نام IoCC انجام شود که در بخش بعد شرح داده می‌شود.ابزار IoCCابزار IoCC یا Inversion of Control Container طراحی شده‌اند‌ تا با استفاده از آن اصل Dependency inversion در پروژه رعایت شود. این ابزار در ابتدای اجرای پروژه لیست Abstraction ها و پیاده سازی های آنها را دریافت می‌کنند و در ادامه هنگامی که یک ماژول به یک Abstraction نیاز داشت، پیاده سازی مناسب را در اختیار آن ماژول قرار می‌دهند.در پروژه های PHP می‌توانید از miladrahimi/phpcontainer بعنوان IoCC پروژه استفاده کنید. در پروژه های Laravel می‌توانید از IoCC خود لاراول استفاده کنید.فریم ورک Laravel مجهز به یک IoCC قوی و انعطاف پذیر است. بسیاری از متد ها در پروژه توسط این ابزار فراخوانی می‌شود تا وابستگی های مورد نیاز را تزریق کند. برخی از متد هایی که توسط IoCC لاراول فراخوانی می‌شوند را در زیر می‌بینید.متد های Constructor در Controller هامتد های Controller که نقش Action برای یک Route ایفا می‌کنند (مانند create در مثال بالا)متد های handle مربوط به Middleware هامتد های handle مربوط به Job هامتد های handle مربوط به Command هادر متد register از کلاس App/Providers/AppServiceProvider می‌توانید تعیین کنید که به هنگام نیاز ماژول های پروژه به یک Abstraction، کدام پیاده سازی برای آنها فراهم شود. این فرایند، Bind کردن نام دارد و اصطلاحا Interface یا Abstraction ها را به پیاده سازی های آنها Bind می‌کنیم.برای مثال در یک پروژه، کد زیر در متد register، اینترفیس Email را به پیاده سازی آن که Gmail می‌باشد، Bind می‌کند.class AppServiceProvider extends ServiceProvider {
    public function register() {
        $this-&gt;app-&gt;bind(Email::class, Gmail::class);
    }
    // ...
}اکنون، UsersController را در این پروژه نظر بگیرید.class UsersContronller extends Controller {
    public function create(Request $request, Email $email) {
        // Save user information into database
        $this-&gt;email-&gt;send($user-&gt;email, &#039;Welcome dear user...&#039;);
    }
}می‌دانیم که متد create بعنوان یک Action توسط IoCC لاراول فراخوانی می‌شود تا وابستگی های مورد نیاز آن تزریق شود. با توجه به Binding تعریف شده، IoCC لاراول پیاده سازی Gmail بعنوان پارامتر این متد تزریق می‌کند.علاوه بر متد های معرفی شده برای تزریق وابستگی، مستقیم از خود IoCC نیز می‌توانیم پیاده سازی مورد نیاز را درخواست کنیم. برای مثال کد زیر پیاده سازی مربوط به اینترفیس Email را از IoCC درخواست می‌کند.$email = app(Email::class);
// $email will be an object of Gmailاگر به این روش علاقه‌مند هستید، می‌توانید UsersController را به شکل زیر هم نوشت.class UsersContronller extends Controller {
    public function create(Request $request) {
        // Save user information into database
        app(Email::class)-&gt;send($user-&gt;email, &#039;Welcome dear user...&#039;);
    }
}حال اگر تصمیم بگیریم که در پروژه بجای Gmail از سرویس ایمیل Mailgun استفاده کنیم تنها کافیست متد register در کلاس App/Providers/AppServiceProvider را بصورت زیر تغییر دهیم.$this-&gt;app-&gt;bind(Email::class, Mailgun::class);اصل Open-closed در SOLIDاصل Open-closed (باز-بسته) در در برنامه نویسی شی گرا و اصول SOLID، بر باز بودن ماژول ها برای گسترش یافتن و بسته بودن آنها برای اصلاح تاکید دارد. به بیان ساده تر، ماژول های برنامه نویسی باید طوری طراحی شوند که گسترش آنها راحت باشد تا گسترش به اصلاح ترجیح داده شود.برای مثال، کلاس زیر مسئول ساخت کد ورود کاربران، ذخیره و ارسال آن به شماره همراه کاربر است.class Otp {
    public function make(User $user) {
        $code = andom_int(1000, 9999);

        $userOtp = new UserOtp();
        $userOtp-&gt;user_id = $user-&gt;id;
        $userOtp-&gt;code = $code;
        $userOtp-&gt;save();

        app(Sms::class)-&gt;send($user-&gt;cellphone, $code);
    }
}مشکل کلاس بالا وقتی مشخص می‌شود که مثلا به دلیلی مانند افزایش سرعت سایت، تصمیم بگیریم به جای ذخیره کد های OTP در دیتابیس (MySQL)، آنها را در Redis ذخیره کنیم. آنگاه به ناچار باید کلاس بالا را اصلاح کنیم و اصل Open-closed از اصول SOLID نقض می‌شود.حال کلاس بالا را بازنویسی می‌کنیم و کلاس و Interface های جدیدی معرفی می‌کنیم تا ماژول نهایی از اصل Open-closed از اصول SOLID پیروی کرده باشد.interface OtpStorage {
    function save(string $cellphone, int $code);
}
class MySQL implements OtpStorage {
    function save(string $cellphone, int $code) {
         $userOtp = new UserOtp();
         $userOtp-&gt;user_id = $user-&gt;id;
         $userOtp-&gt;code = $code;
         $userOtp-&gt;save();
    }
}
class Redis implements OtpStorage {
    function save(string $cellphone, int $code) {
        Redis::put($cellphone, $code);
    }
}
class Otp {
    public function make(User $user) {
        $code = random_int(1000, 9999);
        app(OtpStorage::class)-&gt;save($user-&gt;id, $code);
        app(Sms::class)-&gt;send($user-&gt;cellphone, $code);
    }
}حال برای تغییر روش ذخیره سازی کد های ورود کاربران از MySQL به Redis، تنها کافیست که Binding آن در متد register از کلاس App/Providers/AppServiceProvider از$this-&gt;app-&gt;bind(OtpStorage::class, MySQL::class);به صورت زیر تغییر کند:$this-&gt;app-&gt;bind(OtpStorage::class, Redis::class);و دیگر هیچ تغییری در کلاس Otp نخواهیم داشت. اکنون کلاس Otp قابلیت گسترش یافتن (افزودن روش های ذخیره سازی جدید) را دارد اما نیازی به اصلاح شدن ندارد.اصول ISP ،SRP و LSP در SOLIDاصل SRP یا Single-responsibility principle (تک مسئولیتی) در برنامه نویسی شی گرا و اصول SOLID، بر تک کاربرد (مسئولیت) بودن ماژول ها، کلاس ها و Interface ها تاکید دارد.اصل ISP یا Interface segregation principle (تفکیک رابطه کاربری) در برنامه نویسی شی گرا و اصول SOLID، بر تعدد Interface ها و طراحی آنها بر اساس نیاز کاربر به جای طراحی یک Interface جامع تاکید می‌کند.اصل LSP یا Liskov substitution principle (جایگزینی لیسکوف) در برنامه نویسی شی گرا و اصول SOLID، بر قابلیت جایگزین شدن Type با Subtype های آن Type تاکید دارد. بعنوان مثال مربع یک Subtype از مستطیل است، پس اگر این اصل در پروژه رعایت شده باشد، ماژولی که مستطیل را بعنوان ورودی قبول می‌کند باید بتواند مربع را هم به عنوان ورودی بپذیرد.سه اصل ذکر شده را با یک مثال و در رابطه با استفاده صحیح از Interface ها شرح می‌دهیم.برای مثال، Interface زیر را در نظر بگیرید:interface Notification {
    function sendSms(string $to, string $content);
    fucntion sendEmail(string $to, string $contnet);
}واضح ترین اصلی که در طراحی Interface بالا رعایت نشده، اصل Single-responsibility است. این Interface  می‌تواند به دو Interface (یکی Email و دیگری Sms) تقسیم شود. برای رعایت این اصل باید Interface را تا جایی که امکان دارد خرد کنیم تا به Interface هایی برسیم که تنها یک مسئولیت دارند.طبق اصل Interface segregation که مختص به طراحی Interface هاست نیز بر طراحی طبق نیاز کاربر تاکید دارد. برای مثال UsersController که در بخش های قبلی معرفی شد تنها به ارسال Email نیاز دارد اما این Interface قابلیت ارسال SMS هم در خود جای داده که بیشتر از نیاز کاربر (UsersController) است و در نتیجه این اصل هم از اصول SOLID نقض شده است.مشکل بزرگتری که این Interface دارد به هنگام پیاده سازی آن مشخص می‌شود. واضح است که این Interface تنها پیاده سازی هایی را می‌تواند قبول کند که هم خدمات Email و هم خدمات SMS ارائه می‌دهد. برای مثال اگر بخواهیم پیاده ‌سازی مانند Gmail داشته باشیم که تنها متد sendEmail را می‌تواند پوشش دهد و متد sendSms را خالی رها کنیم آنگاه باید دقت کنیم که ماژولی که Gmail را به آن تزریق می‌کنیم تلاش نکند با استفاده از آن SMS ارسال کند. به بیانی، به همه ماژول هایی که به اینترفیس Notification نیاز دارند نمی‌توانیم Gmail را تزریق کنیم چرا که ممکن است به sendSms نیاز داشته باشد و اگر Notification را Type و Gmail را Subtype آن در نظر بگیریم، اصل Liskov substitution از اصول SOLID را نقض کرده ایم.سخن پایانیدر این مقاله سعی کردیم کاربرد ها و نحوه استفاده صحیح از Interface ها را در PHP و Laravel شرح دهیم. برای شرح این موارد به اصول SOLID تکیه کردیم. هم Interface و هم اصول SOLID کاربرد های فراتری دارند که قطعا در یک مقاله کوتاه نمی‌توان جا داد. با این وجود امیدوارم این مقاله توانسته باشد شما را با این دو مهم در برنامه نویسی آشنا کرده باشد.</description>
                <category>میلاد رحیمی</category>
                <author>میلاد رحیمی</author>
                <pubDate>Sun, 11 Apr 2021 15:45:43 +0430</pubDate>
            </item>
                    <item>
                <title>مفاهیم پایه برنامه نویسی وب</title>
                <link>https://virgool.io/CodeLovers/%D9%85%D9%81%D8%A7%D9%87%DB%8C%D9%85-%D9%BE%D8%A7%DB%8C%D9%87-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87-%D9%86%D9%88%DB%8C%D8%B3%DB%8C-%D9%88%D8%A8-ej0jjij018ll</link>
                <description>این مقاله برای علاقه‌مندانی است که با مفاهیم مقدماتی برنامه نویسی آشنا هستند و می‌خواهند به حوزه برنامه نویسی وب وارد شوند. در این مقاله مفاهیم پایه برنامه نویسی وب (Backend و Frontend)، مفاهیم پایه شبکه، پروتکل های شبکه، سرور ها، نحوه اجرای اپلیکیشن های سمت سرور و ارتباط آنها با کلاینت‌ها و نحوه ارتباط بین اپلیکیشن های سرور شرح داده می‌شود. محتوای هر بخش کوتاه و تنها به قصد آشنایی با موضوع تهیه شده است.برنامه نویسی وبشبکه های کامپیوتریشبکه های کامپیوتری برای به اشتراک گذاری منابع (داده، نرم افزار و سخت افزار) ایجاد می‌شوند. با استفاده از یک شبکه می‌توان دو یا چند دستگاه (Device) از جمله کامپیوتر و موبایل را به هم وصل کرد و منابع را بین آنها به اشتراک گذاشت. به هر دستگاه متصل به شبکه گره (Node) گفته می‌شود.برای ایجاد یک شبکه کامپیوتری از سخت افزار هایی همانند سوییچ (Switch)، مودم (Model)، روتر (Router) و غیره استفاده می‌شود. از آنجایی که در این مقاله تمرکز روی لایه های نرم افزاری می‌باشد، از جزئیات مربوط به سخت افزار های شبکه صرف نظر می‌کنیم.بیشتر بخوانید:https://en.wikipedia.org/wiki/Computer_networkانواع شبکه های کامپیوتریشبکه های کامپیوتری از لحاظ گستردگی به دسته هایی همچون PAN، LAN، MAN،‌ WAN و غیره تقسیم می‌شوند.شبکه های PAN یا Personal Area Network با استفاده تکنولوژی هایی با برد (مسافت) کم مانند بلوتوث، Hotspot گوشی یا مودم های خانگی ایجاد می‌شوند تا وسایل شخصی همچون لپ تاپ و موبایل را در یک شبکه قرار دهد.شبکه های LAN یا Local Area Network شبکه های خصوصی هستند که در ادارات، شرکت ها، کافی‌نت ها و دیتاسنتر ها رایج هستند.به همین ترتیب شبکه های MAN و WAN ابعاد بزرگتری مانند یک شهر یا کشور را پوشش می‌دهند.بیشتر بخوانید:https://www.belden.com/blogs/network-typesاینترنتاینترنت شبکه‌ای از شبکه هاست که وسعتی بزرگ تر از کره زمین دارد و طراحی شده تا مردم در سراسر کره زمین بتوانند به وسیله آن با هم در ارتباط باشند از منابع به اشتراک گذاشته شده استفاده کنند.مهم ترین شبکه های موجود در اینترنت، شبکه های متعلق به دیتاسنتر (Data Center) ها هستند. دیتاسنتر ها سرور های فیزیکی که به اینترنت متصل هستند را به شرکت های نرم افزاری و توسعه دهنده ها ارائه می‌دهند.بیشتر بخوانید:https://en.wikipedia.org/wiki/Internethttps://en.wikipedia.org/wiki/Data_centerآدرس IPپس از ایجاد یک شبکه، به هر دستگاه یک آدرس IP (Internet Protocol) اختصاص داده می‌شود. آدرس IP را از جهاتی می‌توان به کد پستی تشبیه کرد و همانطور که کد پستی به یک خانه خاص مرتبط می‌شود،‌ آدرس IP هم به یک Node خاص در شبکه اشاره می‌کند و جهت آدرس‌دهی استفاده می‌شوند.دستگاه های متصل به شبکه برای ارتباط با یکدیگر از آدرس های IP استفاده می‌کنند. برای مثال در شکل زیر، دو کامپیوتر با IP های 192.168.0.1 و 192.168.0.2 در یک شبکه خصوصی قرار دارند. این دو کامپیوتر با داشتن آدرس IP یکدیگر می‌توانند در آن شبکه با هم ارتباط برقرار کنند.آدرس IP و ارتباط دو Node در شبکهدر زمان نوشتن این مقاله، IP در دو نسخه IPv4 و IPv6 وجود دارد. نسخه IPv6 که در سال ۲۰۱۷ به عنوان استاندارد پذیرفته شد در حال رشد می‌باشد، با این وجود هنوز در بیشتر شبکه ها از IPv4 استفاده می‌شود. در این بخش و مثال های این مقاله نیز از نسخه IPv4 استفاده شده است اما ادامه مباحث فارغ از نسخه IP می باشد.یک IP (نسخه IPv4) از چهار عدد (بین 0 تا 255) که با نقطه جدا شده‌اند تشکیل می‌شود. بیشتر IP ها برای اینترنت استفاده می‌شوند. یک سری از IP ها نیز برای شبکه های خصوصی و loopback رزرو شده‌اند تا تداخلی با IP های اینترنت نداشته باشند.برای مثال رنج IP های زیر برای استفاده در شبکه های خصوصی رزرو شده‌اند.192.168.0.0 تا 192.168.255.255172.16.0.0 تا 172.31.255.255یک سری از IP ها نیز Loopback نام دارند و به خود Node مبدا اشاره می‌کند. کاربرد این سری از IP های برای تست و ارتباط Node با خودش است. برای ارتباط از طریق این IP ها نیازی به اتصال به اینترنت یا شبکه خصوصی روی Node نیست. معروف‌ترین این IP ها 127.0.0.1 است.بیشتر بخوانید:https://en.wikipedia.org/wiki/IP_addresshttps://en.wikipedia.org/wiki/Reserved_IP_addresseshttps://en.wikipedia.org/wiki/Localhostدامنه (Domain) و DNSدامنه (Domain) کاربرد های مختلفی در شبکه ها و بخصوص اینترنت دارد. یکی از مهمترین کاربرد آن نامگذاری روی سرویس (یا Node) های موجود در شبکه است. با وجود یک سرور DNS (Domain Name System) در شبکه که همانند یک دفترچه تلفن برای نگاشت بین دامنه ها و IP ها استفاده می‌شود، Node های موجود در شبکه می‌توانند بجای آدرس IP با استفاده از دامنه با هم ارتباط برقرار کنند.برای مثال در اینترنت، دامنه nic.ir به آدرس آی‌پی 194.225.70.16 اشاره می‌کند. در نتیجه یک نود در اینترنت (برای مثال یک کاربر متصل به اینترنت) به جای ارتباط با 194.225.70.16 می‌تواند با دامنه nic.ir ارتباط برقرار کند. برای مثال شما در مرورگر خود می‌توانید دامنه nic.ir را به جای 194.225.70.16 وارد کنید.بیشتر بخوانید:https://en.wikipedia.org/wiki/Domain_namehttps://en.wikipedia.org/wiki/Domain_Name_Systemhttps://en.wikipedia.org/wiki/Name_serverشماره Portهمانطور که قبلا اشاره شد، یک نود در شبکه با داشتن آدرس IP نود دیگر می‌تواند با آن نود ارتباط برقرار کند. اما اگر بخواهیم دقیق تر به این قضیه نگاه کنیم، باید اصلاح کرد که این ارتباط بین اپلیکیشن های موجود بر روی Node ها صورت می‌پذیرد نه خود Node ها.هر Node می‌تواند میزبان یک یا چند اپلیکیشن متقاضی ارتباط در شبکه باشد. سیستم عامل هر Node به اپلیکیشن های روی آن Node شماره Port هایی اختصاص می‌دهد. همانند آدرس IP که در یک شبکه متعلق به یک Node است، هر شماره Port در یک Node متعلق به یک اپلیکیشن بر روی آن Node می‌باشد. در نتیجه، هر اپلیکیشن با داشتن آدرس IP نود دیگر و شماره Port اپلیکیشن مورد نظر بر روی آن Node می‌تواند با آن اپلیکیشن ارتباط برقرار کند.برای مثال در شکل زیر اگر اپلیکیشن A بر روی کامپیوتر C1 بخواهد با اپلیکیشن D بر روی کامپیوتر C2 ارتباط برقرار کند باید آدرس IP کامپیوتر C2 که 192.168.0.2 است و شماره Port اپلیکیشن D که 18 می‌باشد را داشته باشد.اپلیکیشن ها و پورت ها چنانچه از Loopback IP ها مانند 127.0.0.1 استفاده شود، با استفاده از پورت ها حتی بدون اتصال به شبکه یا اینترنت، اپلیکیشن های روی یک Node هم می‌توانند با هم ارتباط برقرار کنند. برای مثال، در نود C1 اپلیکیشن B می‌تواند با پورت 33 و آدرس آی‌پی 127.0.0.1 با اپلیکیشن C ارتباط برقرار کند. امکان ارتباط این دو اپلیکیشن با استفاده از IP شبکه 192.168.0.1 هم وجود دارد، اما در این صورت اطلاعات برای منتقل شدن از Node خارج و وارد شبکه می‌شود و با مسیریابی شبکه مجددا به خود Node برمی‌گردد که در نتیجه شاهد افت سرعت نسبت به ارتباط از طریق Loopback IP خواهیم بود.بیشتر بخوانید:https://en.wikipedia.org/wiki/Port_(computer_networking)https://en.wikipedia.org/wiki/Localhostآدرس Socketبه ترکیب آدرس IP یا Domain مربوط به یک Node و شماره Port یک اپلیکیشن موجود روی آن Node آدرس Socket گفته می‌شود. آدرس سوکت معمولا بصورت IP:Port (برای مثال 192.168.0.2:18 یا nic.ir:80) نوشته می‌شود. آدرس سوکت به یک اپلیکیشن خاص در شبکه اشاره می‌کند و ارتباط اپلیکیشن های موجود در شبکه با داشتن آدرس سوکت میسر می‌شود.برای نوشتن اپلیکیشن هایی که می‌خواهند بر روی یک شبکه با هم ارتباط برقرار کنند، می‌توان از زبان های برنامه نویسی که قابلیت برنامه نویسی سوکت (Socket Programming) را ارائه می‌دهند استفاده کرد. از جمله زبان هایی که قابلیت برنامه نویسی سوکت را ارائه می‌دهند، می‌توان به جاوا، PHP، پایتون، Go، سی و ++C اشاره کرد.بیشتر بخوانید:https://en.wikipedia.org/wiki/Network_socketمدل کلاینت و سرورارتباط بین اپلیکیشن های موجود بر روی شبکه معمولا بصورت درخواست و پاسخ (Request/Response) می‌باشد. برای مثال، اپلیکیشن A میزبان اطلاعات کاربران می‌باشد و اپلیکیشن B مسئول ایجاد کد تخفیف به مناسبت زادروز کاربران است. اپلیکیشن B برای دریافت اطلاعات کاربران می‌تواند یک درخواست به اپلیکیشن A بفرستد و اپلیکیشن A در پاسخ لیست کاربران را برگرداند.اپلیکیشن درخواست کننده را اپلیکیشن کلاینت (Client Application) و اپلیکیشن پاسخ دهنده (سرویس دهنده) را اپلیکیشن سرور (Server Application) می‌گویند. Node میزبان اپلیکیشن های کلاینت را بطور مختصر کلاینت و Node میزبان اپلیکیشن های سرور را بطور مختصر سرور می‌نامند.client = new SocketClient()
users = client.send(&#039;192.168.0.1:33&#039;, &#039;Give me the list of users&#039;)
// Rest of the processشبه کد بالا متعلق به اپلیکیشن کلاینت (B) است و به یک زبان فرضی شی‌گرا نوشته شده است. در این شبه کد، یک درخواست با محتوای «Give me the list of users» به سوکت 192.168.0.1:33 (اپلیکیشن A) فرستاده می‌شود و پس از دریافت پاسخ، آنرا در متغیر users می‌ریزد.server = new SocketServer()
server.listen(33, function(request) {
    switch (request) {
        case &#039;Give me the list of users&#039;:
            return UserRepository.all().toJson()
        else:
            return &#039;Bad Request&#039;
    }
})شبه کد بالا متعلق به اپلیکیشن سرور (A) است که روی یک Node با آدرس 192.168.0.1 در حال اجرا است. این اپلیکیشن به Port شماره 33 گوش می‌دهد و با دریافت هر درخواست، تابع (Function) پردازش درخواست را فراخوانی می‌کند. در تابع مربوطه، با توجه به محتوای درخواست، پاسخ مناسب بازگردانده می‌شود.مدل کلاینت و سرور در طراحی سیستم های مبتنی بر اینترنت، شبکه های خصوصی و برای ارتباط اپلیکیشن های روی یک Node کاربرد دارد. مثالی از این مدل سرویس های تلگرام، اینستاگرام و ... می‌باشد که اپلیکیشن کلاینت همان نسخه اندروید، iOS و وب می‌باشد که کاربر نصب می‌کند و اپلیکیشن سرور بر روی سرور سرویس مورد نظر اجرا شده و به اپلیکیشن های کلاینت سرویس می‌دهد. مثالی دیگر از این مدل، ارتباط یک اپلیکیشن نصب شده روی سرور (اینبار بعنوان اپلیکیشن کلاینت!) با یک پایگاه داده (Database) مانند MySQL (بعنوان اپلیکیشن سرور) می‌باشد که بواسطه این ارتباط اپلیکیشن می‌تواند داده ها را در دیتابیس ذخیره یا بخواند.بیشتر بخوانید:https://en.wikipedia.org/wiki/Client%E2%80%93server_modelپروتکلدر مثال اپلیکیشن های کلاینت و سرور در بخش قبل، کلاینت پیغام «Give me the list of users» را به اپلیکیشن سرور می‌فرستد و اپلیکیشن سرور نیز به گونه‌ای طراحی شده که با دریافت درخواستی با این محتوا، لیست همه کاربران را بعنوان پاسخ بازگرداند. به بیان دقیق‌تر، قراردادی ایجاد شده که هر دو اپلیکیشن های کلاینت و سرور آنرا متوجه می‌شوند. در این قرارداد، درخواستی با محتوای «Give me the list of users» برای دریافت لیست همه کاربران تعریف شده است. به قرارداد هایی که تعریف می‌شوند تا اپلیکیشن های کلاینت و سرور طبق آن با هم ارتباط برقرار کنند، پروتکل (Protocol) می‌گویند.در صورتی که شما توسعه دهنده اپلیکیشن های کلاینت و سرور باشید، به دلخواه خود می‌توانید پروتکل را تعریف کنید. در واقعیت بسیاری از امکانات طراحی شده بر روی شبکه ها همچون وب، ایمیل و SSH، بصورت عمومی تعریف می‌شوند و اپلیکیشن های متفاوتی توسط شرکت های مختلفی برای آنها پیاده‌سازی می‌شود. در این صورت لازم است تا پروتکل های استانداردی تعریف شود و همه تولیدکنندگان اپلیکیشن طبق آن عمل کنند.برای نمونه یکی از امکانات مفیدی که با استفاده از شبکه ایجاد شده ایمیل می‌باشد. پروتکل SMTP برای ارسال ایمیل مورد استفاده قرار می‌گیرد. برای اینکه به شخصی ایمیل بفرستید، باید بر روی یک نود از شبکه، یک اپلیکیشن (همانند Gmail) داشته باشید که با استفاده از پروتکل SMTP بتواند متن ایمیل را به سوکت مقصد (ارائه دهنده سرویس ایمیل مخاطب مانند Gmail یا Yahoo) ارسال کند.یک پروتکل فرضی برای ارسال ایمیل می‌تواند به شکل زیر باشد:درخواست:Email Sending Protocol v1.0
From: info@miladrahimi.com
To: jack@example.com
Message: &#039;Hello Jack!&#039;پاسخ:Result: OKبیشتر بخوایند:https://www.manageengine.com/network-monitoring/network-protocols.htmlhttps://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocolوبیکی از کاربرد های شبکه و بخصوص اینترنت وب می‌باشد. وب بر پایه دو پروتکل HTTP و HTTPS ایجاد شده است. کاربرد این پروتکل ها، دریافت و ارسال صفحات وب (HTML)، انواع فایل ها، انواع اطلاعات در فرمت های مختلف همانند JSON و XML و ... می‌باشد.تفاوت دو پروتکل HTTP و HTTPS تنها وجود رمزنگاری در HTTPS است. به این صورت که در HTTPS، درخواست از سمت کلاینت رمزنگاری و در سمت سرور رمزگشایی می‌شود. پاسخ HTTP نیز در سمت سرور رمزنگاری و در سمت کلاینت رمزگشایی می‌شود.در سمت سرور، اپلیکیشن سرور قرار دارد که سرویس مربوطه را ارائه می‌دهد. در مورد دریافت و ارسال صفحات وب (HTML)، اپلیکیشن کلاینت می‌تواند یکی از مرورگر های معروف مانند Chrome یا Firefox باشد. در مورد دریافت و ارسال اطلاعات با فرمت JSON، کلاینت می‌تواند یک اپلیکیشن موبایل، دسکتاپ یا اسکریپت داخلی یک صفحه وب باشد. در مورد دریافت و ارسال فایل، کلاینت می‌تواند یک مرورگر یا دانلود منیجر باشد.بیشتر بخوانید:https://en.wikipedia.org/wiki/World_Wide_Webhttps://en.wikipedia.org/wiki/HTTPSدریافت و ارسال HTMLارسال و دریافت صفحات وب (HTML) یکی از امکانات وب است. در سمت کلاینت معمولا از مرورگر های وب مانند Chrome و Firefox استفاده می‌شود. در سمت سرور اپلیکیشن ارائه دهنده سرویس (وب‌سایت) قرار دارد.بیشتر وبسایت ها از تعدادی صفحه وب (HTML) تشکیل شده‌اند. این صفحه ها با درخواست HTTP کاربر از طریق کلاینت های HTTP همچون مرورگر ها، در اختیار کاربر قرار می‌گیرند. بعضی از این صفحات یک کد HTML ثابت و برخی با توجه به درخواست ورودی و بعد از پردازش آن، کد HTMLی را تولید و به کاربر می‌دهند.برای مثال، اگر شما در مرورگر سایت https://google.com را درخواست کنید. مرورگر شما یک درخواست HTTPS (همان HTTP رمزنگاری شده) به سرور گوگل با دامنه google.com و پورت 443 (پورت پیشفرض برای پروتکل HTTPS) می‌فرستد. سرور گوگل با دریافت درخواست، صفحه HTML مربوط به صفحه اصلی (خانه) خود را بعنوان پاسخ HTTP به مرورگر می‌فرستد.درخواست و پاسخ HTTP بین مرورگر و سروربیشتر بخوانید:https://en.wikipedia.org/wiki/Web_browserhttps://en.wikipedia.org/wiki/HTMLآدرس صفحات وبصفحات وب (و فایل ها) با URL (کوتاه شده‌ی Uniform Resource Locator) آدرس دهی می‌شوند. مرورگر ها، کلاینت های وب همچون cURL و کتابخانه های برنامه نویسی معمولا URL را بعنوان ورودی برای دسترسی به یک فایل یا صفحه وب در اینترنت دریافت می‌کنند. ساختار یک URL ساده (بدون اطلاعات هویت) بصورت زیر است:scheme://host/[path][?query]برای مثال:https://shop.com/products?id=13
http://example.com:33/page.htmlدر این ساختار:بخش scheme پروتکل را مشخص می‌کند که می‌تواند http یا https باشد.بخش host دامنه یا IP و Port را مشخص می‌کند.بخش path آدرس صفحه یا سرویس داخلی را مشخص می‌کند.بخش query پارامتر های ورودی مورد نیاز صفحه یا سرویس داخلی را مشخص می‌کند.در صوتی که در بخش host تنها دامنه یا IP وارد شود، اپلیکیشن کلاینت (مرورگر) بطور پیشفرض پورت 80 را برای پروتکل HTTP و پورت 443 را برای پروتکل HTTPS در نظر می‌گیرد. برای مثال دو آدرس زیر یکسان می‌باشند و مرورگر host اولی را بطور پیشفرض با پورت 443 درنظر می‌گیرد.https://miladrahimi.com/pay.html
https://miladrahimi.com:443/pay.htmlبه همین خاطر معمولا اپلیکیشن های سمت سرور که سرویس وب را ارائه می‌دهند طوری طراحی می‌شوند که به پورت های 80 و 443 گوش کنند.بیشتر بخوانید:https://en.wikipedia.org/wiki/URLhttps://en.wikipedia.org/wiki/Uniform_Resource_Identifierپروتکل HTTPهمانطور که قبلا اشاره شد برای وب از پروتکل HTTP (یا نسخه رمزنگاری شده آن HTTPS) استفاده می‌شود. در زیر یک درخواست HTTP که مرورگر به هنگام وارد شدن آدرس http://miladrahimi.com/pay.html به مقصد miladrahimi.com:80 می‌فرستند را مشاهده می‌کنید.GET /pay.html HTTP/1.1
Host: miladrahimi.comدرخواست HTTP دارای دو قسمت Header و Body است (با تگ های head و body در HTML اشتباه نگیرید) که با یک خط خالی جدا می‌شوند. در خواست فوق تنها Header دارد و فاقد بخش Body می‌باشد.در خط اول این درخواست HTTP:عبارت GET متد درخواست است. متد های مختلف طراحی شده‌اند تا بتوانند از یک URL برای کاربرد های مختلفی استفاده کنند. متد درخواست هایی که مرورگر پس از وارد شدن URL توسط کاربر ایجاد می‌کند GET است.عبارت pay.html/ مسیر (Path) درخواست است که معادل Path مربوط به URL است.عبارت HTTP/1.1 نسخه پروتکل را مشخص می‌کند.خط دوم از Header درخواست بصورت Key: Value نوشته شده است. در این درخواست یک Host وجود دارد که برابر miladrahimi.com می‌باشد. هدر Host به این دلیل لازم می‌باشد که ممکن است اپلیکیشن سرور، سرویس های مختلفی را از طریق چند دامنه متفاوت ارائه دهد و نیاز داشته باشد بداند درخواست HTTP دریافتی برای کدام دامنه بوده است.اپلیکیشن کلاینت (مرورگر) می‌تواند در خط های بعدی Header، اطلاعات دیگری همانند نام و نسخه خودش، سیستم عامل کاربر و ... را در درخواست بگنجاند.در زیر پاسخ HTTP که اپلیکیشن سرور miladrahimi.com:80 بعنوان پاسخ به درخواست HTTP فوق برمی‌گرداند را می‌بینید.HTTP/1.1 200 OK
Content-type: text/html

&lt;html&gt;
...
&lt;/html&gt;همانند درخواست HTTP، پاسخ HTTP نیز دارای دو قسمت Header و Body است که با یک خط خالی جدا می‌شوند. در قسمت Header اطلاعات مربوط به نوع و محتوای پاسخ و در قسمت Body محتوای پاسخ (کد HTML صفحه یا محتوای فایل) قرار می‌گیرد.در مثال بالا عبارت HTTP/1.1 نسخه پروتکل را نشان می‌دهد. عدد 200 کد وضعیت و عبارت OK نام وضعیت پاسخ است. در زیر لیست وضعیت های پر استفاده HTTP را می‌بینید.200 OK (سرور درخواست کاربر را با موفقیت پاسخ می‌دهد)204 No Content (سرور با موفقیت درخواست را انجام داده اما محتوایی برای بازگرداندن ندارد)301 Moved Permanently (منبع مورد نظر برای همیشه به آدرس دیگری منتقل شده)303 See Other (سرور از کلاینت می‌خواد در ادامه به آدرس دیگری رجوع کند)400 Bad Request (درخواست کاربر دارای مشکل است)401 Unauthorized (سرور قادر به تشخیص کاربر درخواست کننده نیست)403 Forbidden (کاربر دسترسی لازم برای مشاهده منبع را ندارد)404 Not Found (منبع یا صفحه مورد نظر وجود ندارد)500 Internal Error (سرور با خطای داخلی مواجه شده و قادر به پاسخ دادن نیست)بخش Body پاسخ حاوی کد HTML صفحه وب درخواست شده است که اگر کلاینت یک مرورگر باشد، آن را Render می‌کند و خروجی را به کاربر نمایش می‌دهد. در صورتی صفحه HTML حاوی Asset (فایل های CSS، جاوااسکریپت، تصویر، ویدیو و ...) باشد، به ازای هر کدام از آنها، مرورگر یک درخواست مشابه به سرور می‌فرستد تا بعنوان پاسخ محتوای هر یک را دریافت کند و در پروسه Render، آنها را لحاظ کند.بیشتر بخوانید:https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocolhttps://en.wikipedia.org/wiki/HTTPShttps://en.wikipedia.org/wiki/List_of_HTTP_status_codesکوکی (Cookie)یکی از امکاناتی که در مرورگر ها و برخی از کلاینت های وب (HTTP) پیاده سازی شده، پشتیبانی از کوکی (Cookie) است. کوکی بصورت یک پایگاه داده Key/Value است که از طرف اپلیکیشن کلاینت (مرورگر) در اختیار سایت ها قرار می‌گیرد.اپلیکیشن سرور با قراردادن هدر مربوط به کوکی در پاسخ های HTTP می‌تواند به اپلیکیشن کلاینت خبر دهد که اطلاعات مورد نیازش را ذخیره کند. اپلیکیشن کلاینت اگر از کوکی ها پشتیبانی کند، اطلاعات دریافتی را ذخیره و در درخواست های HTTP بعدی آنرا در Header درخواست می‌گنجاند.نمونه از یک پاسخ HTTP از اپلیکیشن سمت سرور که نیاز به ذخیره اطلاعات در کوکی دارد:HTTP/1.1 200 OK
Set-Cookie: name=Jack; Max-Age=86400
Set-Cookie: id=33; Max-Age=86400

&lt;html&gt;...&lt;/html&gt;پاسخ HTTP فوق از اپلیکیشن سمت سرور به کلاینت خبر می‌دهد که دو داده مورد نظر را در سمت کلاینت بعنوان کوکی و هر کدام را به مدت ۲۴ ساعت (86400 ثانیه) ذخیره کند. در صورت پشتیبانی اپلیکیشن کلاینت از کوکی، در تمامی درخواست های بعدی تا مدت ۲۴ ساعت، داده های دریافتی برای آن سرور فرستاده می‌شود.در زیر می‌توانید نمونه یک درخواست HTTP که حاوی داده های کوکی دریافتی است را ببینید:GET /profile HTTP/1.1
Host: example.com
Cookie: name=Jack; id=33مهمترین کاربرد کوکی، احراز هویت کاربران است. در سمت اپلیکیشن سرور ممکن است درخواست های گوناگونی از کاربران مختلف دریافت شود. اپلیکیشن سرور با استفاده از کوکی می‌تواند کاربر درخواست کننده را تشخیص دهد.بیشتر بخوایند:https://en.wikipedia.org/wiki/HTTP_cookieلاگین کاربران با Cookieاکنون با استفاده از مفاهیم شرح داده شده، درخواست و پاسخ های HTTP مربوط به لاگین کاربران در یک سایت فرضی را بررسی می‌کنیم.در زیر نمونه درخواست با پروتکل HTTP از طرف مرورگر بعد از وارد شدن آدرس http://example.com/login توسط کاربر را می‌بینید:GET /login HTTP/1.1
Host: example.comاین درخواست HTTP اولین درخواست کاربر به example.com:80 است و به همین خاطر هنوز هیچ کوکی در مرورگر ذخیره نشده و درخواست خالی از کوکی می‌باشد.نمونه پاسخ HTTP سایت example.com برای درخواست صفحه خانه از سایت:HTTP/1.1 200 OK

&lt;html&gt;
    &lt;head&gt;&lt;title&gt;Example Login&lt;/title&gt;&lt;/head&gt;
    &lt;body&gt;
        &lt;form action=&#039;/login&#039; method=&#039;POST&#039;&gt;
            &lt;input type=&#039;text&#039; name=&#039;username&amp;quot&gt;
            &lt;input type=&#039;password&#039; name=&#039;password&#039;&gt;
            &lt;button type=&#039;submit&#039;&gt;Login&lt;/button&gt;
        &lt;/form&gt;
    &lt;/body&gt;
&lt;/html&gt;پاسخ HTTP بالا حاوی Header مربوط به وضعیت موفق و Body محتوای HTML صفحه لاگین است. کاربر هنوز در سایت لاگین نکرده و در نتیجه سایت اطلاعاتی جهت ذخیره در کوکی ندارد.مرورگر با دریافت این پاسخ آنرا که یک فرم ورود (لاگین) است به کاربر نمایش می‌دهد. با وارد شدن Username و Password به ترتیب admin و secret توسط کاربر و کلیک بر دکمه Login که دکمه submit فرم ‌می‌باشد، مرورگر درخواست HTTP زیر را به اپلیکیشن سرور می‌فرستد:POST /login HTTP/1.1
Host: example.com
username=admin&amp;password=secretدر مثال های قبلی، همیشه درخواست مرورگر با وارد شدن URL توسط کاربر ایجاد می‌شد و مرورگر بطور پیشفرض متد درخواست را GET در نظر می‌گرفت. اینبار درخواست به خاطر کلیک بر دکمه Login فرم موجود در صفحه وب ایجاد شده است. در چنین حالتی مرورگر متد درخواست را از method تگ form که در اینجا POST است انتخاب می‌کند. مسیر (Path) مربوط به درخواست نیز از action مربوط به تگ form انتخاب می‌شود. در خط سوم درخواست، مرورگر اطلاعات وارد شده توسط کاربر در فیلد های فرم را قرار می‌دهد.درخواست HTTP فوق و درخواستی قبلی دارای URL یکسان (http://example.com/login) می‌باشند اما تفاوت متد آن هاست که در درخواست قبلی متد GET و در خواست فوق متد POST می‌باشد. رفتار اپلیکیشن سرور برای متد های مختلف همانند این مثال می‌تواند متفاوت باشد.با فرض درست بودن Username و Password، از طرف اپلیکیشن سرور (سایت)، چنین پاسخی دریافت می‌شود:HTTP/1.1 303 See Other
Location: http://example.com/profile
Set-Cookie: user_id=13; Max-Age=86400کد پاسخ فوق 303 به معنی نیاز به Redirect کردن کاربر به یک صفحه جدید است. در واقع اپلیکیشن سرور به مرورگر خبر می‌دهد که کاربر را باید به صفحه جدیدی که آدرس آنرا در خط دوم Header می‌بینید منتقل کند. این پاسخ علاوه بر اطلاعات مربوط به انتقال کاربر، حاوی اطلاعاتی برای ذخیره در کوکی (ID کاربر در سرور) نیز می‌باشد.مرورگر با دریافت پاسخ فوق، کوکی دریافتی را ذخیره و درخواست جدیدی برای دریافت صفحه http://example.com/profile می‌فرستد (کاربر Redirect می‌شود). این درخواست حاوی کوکی دریافتی نیز می‌باشد.GET /profile HTTP/1.1
Host: example.com
Cookie: user_id=13اپلیکیشن سمت سرور با دریافت درخواست فوق، متوجه می‌شود که باید صفحه پروفایل مربوط به کاربر با ID=13 را به کلاینت بدهد. پاسخ اپلیکیشن سرور به درخواست به این صورت می‌باشد:HTTP/1.1 200 OK

&lt;html&gt;
    &lt;head&gt;&lt;title&gt;Profile&lt;/title&gt;&lt;/head&gt;
    &lt;body&gt;
        &lt;p&gt;Username: admin&lt;/p&gt;
        &lt;p&gt;Full Name: Milad Rahimi&lt;/p&gt;
    &lt;/body&gt;
&lt;/html&gt;معمولا برای طراحی اپلیکیشن های سمت سرور از زبان و تکنولوژی هایی مانند PHP، جاوا، Node.js، پایتون، Go، سی‌شارپ و ... استفاده می‌شود.سورس کد مربوط به اپلیکیشن سرور مثال بالا به زبان Go (با استفاده از فریم ورک Echo) به این صورت می‌باشد:package main

import (
   &amp;quotfmt&amp;quot
   &amp;quotgithub.com/labstack/echo/v4&amp;quot
   &amp;quotnet/http&amp;quot
   &amp;quotstrconv&amp;quot
)

func main() {
   // New instance of echo framework to handle HTTP requests
   e := echo.New()

   // Login (GET)
   e.GET(&amp;quot/login&amp;quot, func(c echo.Context) error {
      return c.HTML(200, &amp;quot&lt;html&gt;&lt;form&gt;...&lt;/form&gt;&lt;/html&gt;&amp;quot)
   })

   // Login (POST)
   e.POST(&amp;quot/login&amp;quot, func(c echo.Context) error {
      username := c.FormValue(&amp;quotusername&amp;quot)
      password := c.FormValue(&amp;quotpassword&amp;quot)

      user, err := findByUserPass(username, password)
      if err != nil {
         return c.HTML(401, &amp;quot&lt;html&gt;&lt;p&gt;Authorization failed.&lt;p&gt;&lt;/html&gt;&amp;quot)
      }

      c.SetCookie(&amp;http.Cookie{
         Name:   &amp;quotuser_id&amp;quot,
         Value:  user.ID,
         MaxAge: 86400,
      })
      return c.Redirect(303, &amp;quothttp://example.com/profile&amp;quot)
   })

   // Profile (GET)
   e.GET(&amp;quot/profile&amp;quot, func(c echo.Context) error {
      id, err := c.Cookie(&amp;quotuser_id&amp;quot)
      if err != nil {
         return c.HTML(401, &amp;quot&lt;html&gt;&lt;p&gt;Authorization failed.&lt;p&gt;&lt;/html&gt;&amp;quot)
      }

      user, err := findById(id.Value)
      if err != nil {
         return c.HTML(401, &amp;quot&lt;html&gt;&lt;p&gt;Authorization failed.&lt;p&gt;&lt;/html&gt;&amp;quot)
      }

      html := fmt.Sprintf(
         &amp;quot&lt;html&gt;...&lt;p&gt;Username: %s&lt;/p&gt;&lt;p&gt;Full Name: %s&lt;/p&gt;...&lt;/html&gt;&amp;quot,
         user.Username,
         user.FullName,
      )
      return c.HTML(200, html)
   })

   // Start listening to Port 80 (0.0.0.0:80)
   e.Start(&amp;quot:80&amp;quot)
}جلسه (Session)در اپلیکیشن سروری که با استفاده از Cookie برای لاگین کاربران طراحی شد، کاربر با استفاده از اطلاعات ذخیره شده در کوکی تشخیص داده می‌شد. اپلیکیشن کلاینت که در سمت کلاینت است،‌ می‌تواند کوکی متفاوتی برای سرور بفرستد. برای مثال در بالا بجای 13 عدد 33 را بفرستد و آنگاه می‌تواند پروفایل کاربر با ID=33 را ببیند و از طرف او با اپلیکیشن سرور در تعامل باشد و در واقع جعل هویت کند.برای حل مشکل امنیتی احراز هویت کاربر با استفاده از کوکی ها، مکانیزم دیگری بعنوان Session استفاده می‌شود. در این مکانیزم اپلیکیشن سمت سرور، بجای ذخیره اطلاعات مورد نیاز (مثلا ID کاربر) در Cookie، آنرا در یک فایل با نامی رندوم و طولانی (غیر قابل حدس توسط کاربران) در سرور ذخیره می‌کند و تنها نام فایل را در کوکی ذخیره می‌کند. با این مکانیزم کاربر تنها نام Session را در اختیار دارد و بخاطر طولانی و رندوم بودن آن با تغییر آن نمی‌تواند به Session کاربر دیگری دست پیدا کند.نمونه پاسخ HTTP اپلیکیشن سمت سرور پس از لاگین موفق کاربر:HTTP/1.1 303 See Other
Location: http://example.com/profile
Set-Cookie: session=1a2b3c...x4v03d; Max-Age=86400در درخواست های بعدی که مرورگر اطلاعات کوکی را برای اپلیکیشن سرور میفرستد، اپلیکیشن سمت سرور نام فایل سشن را از کوکی دریافتی پیدا می‌کند و اطلاعات کاربر را از فایل ذخیره شده در سمت سرور می‌خواند.بیشتر بخوانید:https://en.wikipedia.org/wiki/Session_(computer_science)جاوا اسکریپت و AJAXجاوا اسکریپت (JavaScript) یک زبان برنامه نویسی چند منظوره می‌باشد. اولین و مهمترین کاربرد این زبان، قابلیت اجرا شدن در مرورگر می‌باشد. کد های JavaScript می‌تواند در میان تگ script در HTML قرار بگیرد تا مرورگر آنرا اجرا کند. هدف از اجرای کد های JavaScript، تغییر تگ های HTML بعد از Load شدن در مرورگر و تعامل با اپلیکیشن سرور می‌باشد.قابلیت تعامل با اپلیکیشن سرور در JavaScript را AJAX می‌گویند. در شکل زیر نحوه این تعامل در کنار درخواست و پاسخ های HTTP را می‌بینید.تعامل جاوا اسکریپت با اپلیکیشن سرور (AJAٓX) در توضیح فرایند بالا، مرورگر پس از وارد شدن URL ذکر شده (http://example.com/page.html) توسط کاربر، یک درخواست HTTP به اپلیکیشن سرور می‌فرستند. اپلیکیشن سرور در پاسخ، صفحه HTML که حاوی کد JavaScript است را به مرورگر کاربر می‌فرستد. مرورگر پس از دریافت پاسخ، صفحه HTML را به کاربر نمایش می‌‌دهد. مرورگر علاوه بر نمایش HTML، کد های JavaScript را نیز اجرا می‌کند. کد JavaScript خود می‌تواند به اپلیکیشن سرور درخواست HTTP بفرستد و پاسخ آنرا دریافت کند و بر اساس پاسخ دریافتی ممکن است تگ های HTML را تغییر دهد. مرورگر برخلاف زمانی که خود درخواست می‌فرستند، با درخواست های HTTP که JavaScript می‌فرستند صفحه را از نو render نمی‌کند و حتی ممکن است کاربر نهایی متوجه این تعامل نشود.بیشتر بخوانید:https://en.wikipedia.org/wiki/JavaScripthttps://en.wikipedia.org/wiki/Ajax_(programming)وب سرویس های مبتنی بر APIنوعی دیگر از سرویس های وب، سرویس های مبتنی بر API می‌باشد. API ها نیز همانند صفحات وب دارای URL می‌باشند با این تفاوت که محتوای (Body) پاسخ های آنها به جای HTML حاوی فرمت های مناسب انتقال اطلاعات همانند JSON و XML است و درخواست های HTTP به جای مقادیر فیلد ها در Header دارای Body حاوی محتوایی با فرمت های مناسب انتقال اطلاعات می‌باشد. اپلیکیشن کلاینت برای صفحات وب معمولا مرورگر ها می‌باشند ولی اپلیکیشن کلاینت برای API ها می‌تواند اسکریپت های JavaScript، اپلیکیشن های موبایل و حتی دیگر اپلیکیشن های سرور باشد.برای مثال، در زیر یک درخواست HTTP به یک API را مشاهده می‌کنید:GET /api/products HTTP/1.1
Host: shop.comو در زیر پاسخ HTTP مربوط به درخواست فوق است که محتوای با فرمت JSON می‌باشد:HTTP/1.1 200 OK

[
    {&amp;quotid&amp;quot: 1, &amp;quotname&amp;quot: &amp;quotMacBook Pro&amp;quot, &amp;quotprice&amp;quot: 1200},
    {&amp;quotid&amp;quot: 2, &amp;quotname&amp;quot: &amp;quotiPhone 13&amp;quot, &amp;quotprice&amp;quot: 980}
]فرمت های انتقال اطلاعات همچون JSON و XML فرمت هایی مناسب برای پردازش توسط اپلیکیشن ها می‌باشد. برای مثال محتوای (JSON) فوق، لیستی از محصولات را نشان ‌می‌دهد که شامل دو محصول و هر محصول داری سه ویژگی id, name و price می‌باشد. بیشتر زبان ها و تکنولوژی های برنامه‌نویسی دارای ابزاری برای خواندن و نوشتن اطلاعات با چنین فرمت هایی هستند.بیشتر بخوانید:https://en.wikipedia.org/wiki/Web_servicehttps://en.wikipedia.org/wiki/Web_APIhttps://en.wikipedia.org/wiki/JSONhttps://en.wikipedia.org/wiki/XMLوب اپلیکیشنوب اپلیکیشن ها به نوعی از وب سایت ها می‌گویند که معمولا دارای یک صفحه HTML حاوی یک اسکریپت JavaScript هستند و بجز درخواست HTTP مربوط به دریافت HTML، بقیه درخواست ها توسط جاوا اسکریپت به API های اپلیکیشن سرور فرستاده می‌شوند.معمولا برای طراحی وب اپلیکیشن ها از فریم ورک های JavaScript همچون Vue.js، React.js و Angular استفاده می‌کنند. نسخه وب واتساپ و اینستاگرام نمونه های از وب اپلیکیشن می‌باشد.بیشتر بخوانید:https://en.wikipedia.org/wiki/Web_applicationhttps://en.wikipedia.org/wiki/Single-page_applicationhttps://en.wikipedia.org/wiki/Progressive_web_applicationاصول RESTبرای طراحی API های یک اپلیکیشن سرور که پاسخ درخواست های یک وب اپلیکیشن (یا اپلیکیشن موبایل یا دیگر اپلیکیشن های سرور) را می‌دهد، معمولا از اصول REST استفاده می‌شود. API و وب اپلیکیشنی که بر اساس اصول REST طراحی شده باشد، RESTful نامیده می‌شود. برخی از اصول REST عبارت‌اند از:استفاده از پروتکل HTTP(S)استفاده از مدل کلاینت و سروراستفاده مفهومی از کد های وضعیت HTTP برای کاربرد های مختلفاستفاده مفهومی از متد های HTTP برای کاربرد های مختلفبرای مثال، در زیر لیستی از API های RESTful برای مدیریت محصولات یک فروشگاه را مشاهده می‌کنید:# List of products
Method=GET, URL=http://shop.com/api/products

# Create a new product
Method=POST, URL=http://shop.com/api/products

# Get a single product information (product id = 13)
Method=GET, URL=http://shop.com/api/products/13

# Update a single product (product id = 13)
Method=PUT, URL=http://shop.com/api/products/13

# Delete a single product (product id = 13)
Method=DELETE, URL=http://shop.com/api/products/13برای مثال درخواست HTTP مربوط به ساخت یک محصول به شکل زیر است:POST /api/products HTTP/1.1
Host: shop.com

{&amp;quottitle&amp;quot: &amp;quotiPhone 7 Plus&amp;quot, &amp;quotprice&amp;quot: 449}و پاسخ HTTP مربوط به درخواست فوق در صورتی که با موفقیت انجام شود به شکل زیر می‌باشد:HTTP/1.1 201 Created

{
    &amp;quotmessage&amp;quot: &amp;quotThe product created successfully.&amp;quot,
    &amp;quotproduct&amp;quot: {&amp;quotid&amp;quot: 33, &amp;quottitle&amp;quot: &amp;quotiPhone 7 Plus&amp;quot, &amp;quotprice&amp;quot: 449}
}اگر مشکلی در اجرای دستور پیش بیاید، برای مثال فرضا عنوان محصولات می‌بایست منحصربفرد باشد و قبلا محصولی با عنوان مورد نظر موجود باشد، پاسخ به شکل زیر می‌باشد:HTTP/1.1 422 Unprocessable Entity

{
    &amp;quoterrors&amp;quot: [
        {&amp;quottitle&amp;quot: [&amp;quotThe title must be unique.&amp;quot]}
    ],
}بیشتر بخوانید:https://en.wikipedia.org/wiki/Representational_state_transferاحراز هویت با توکنپیش‌تر روش احراز هویت کاربران با استفاده از Cookie و Session را که مناسب وب‌سایت های ساده و قدیمی بود شرح داده شد. یک روش مناسب برای احراز هویت کاربران برای وب اپلیکیشن ها، موبایل اپلیکیشن ها و API های بین دو اپلیکیشن سرور، استفاده از توکن (Token) می‌باشد.در احراز هویت با استفاده از توکن، پس از لاگین موفق، اپلیکیشن سرور یک رشته طولانی از حروف و اعداد رندوم و منحصر بفرد برای کاربر تولید می‌کند و در پاسخ HTTP برای کاربر می‌فرستد. اپلیکیشن کلاینت کاربر در درخواست های بعدی که فراخوانی API های نیازمند احراز هویت می‌باشد، توکن دریافت شده را در Header درخواست جای می‌دهد و اپلیکیشن سرور از روی توکن ارسال شده، کاربر را تشخیص می‌دهد.در زیر می‌توانید یک نمونه درخواست HTTP برای لاگین کاربر را ببینید.POST /api/auth/login HTTP/1.1
Host: shop.com

{&amp;quotusername&amp;quot: &amp;quotmilad&amp;quot, &amp;quotpassword&amp;quot: &amp;quot12345678&amp;quot}پاسخ HTTP درخواست فوق در صورتی که اطلاعات ورود صحیح باشد:HTTP/1.1 200 OK

{
    &amp;quottoken&amp;quot: &amp;quotf93n1mM24Eh1b8nWXf9NJrkay3GgQtea&amp;quot,
    &amp;quotuser&amp;quot: {
        &amp;quotusername&amp;quot: &amp;quotmilad&amp;quot,
        &amp;quotemail&amp;quot: &amp;quotinfo@miladrahimi.com&amp;quot,
        &amp;quotname&amp;quot: &amp;quotMilad Rahimi&amp;quot
    }
} پاسخ HTTP درخواست لاگین در صورتی که اطلاعات ناموفق باشد:HTTP/1.1 401 Unauthorizedپاسخ فوق می‌تواند حاوی یک Body با فرمت JSON و پیام خطا باشد ولی اگر بخواهیم مینیمال فکر کنیم نیازی به Body ندارد و کد 401 کافی است!اکنون درخواست HTTP مربوط به ساخت یک محصول را که قبلا در بخش اصول REST مشاهده کردید را با در نظر گرفتن احراز هویت با توکن بازنویسی می‌کنیم.POST /api/products HTTP/1.1
Host: shop.com
Authorization: f93n1mM24Eh1b8nWXf9NJrkay3GgQtea

{&amp;quottitle&amp;quot: &amp;quotiPhone 7 Plus&amp;quot, &amp;quotprice&amp;quot: 449}همانطور که در درخواست فوق قابل مشاهده است، توکن در هدر Authorization جای داده می‌شود. اپلیکیشن سرور با دریافت این درخواست می‌تواند کاربر درخواست کننده را تشخیص دهد. در صورتی که توکن موجود در درخواست اشتباه یا به هر دلیلی اپلیکیشن سرور قادر به تشخیص کاربر از روی آن نباشد، اپلیکیشن سرور می‌تواند خطای 401 Unauthorized را به اپلیکیشن کلاینت بازگرداند. اپلیکیشن کلاینت نیز بهتر است طوری طراحی شود که با دریافت این خطا به کاربر فرم لاگین رو نمایش دهد تا فرایند احراز هویت (لاگین) از سر گرفته شود.وب سایت های استاتیکوب‌سایت های استاتیک به وب‌سایت هایی گفته می‌شود که از تعدادی فایل HTML و Asset های مورد نیاز آن همانند فایل های CSS و JavaScript و فایل های معمولی مانند تصاویر، ویدیو ها، فایل های صوتی و ... تشکیل شده است. در این وب سایت ها، هر درخواست HTTP از طرف کلاینت به یک فایل در سرور منتهی می‌شود و اپلیکیشن سرور تنها مسئول ارائه دادن محتوای فایل ها به کلاینت است. همانطور که مشخص است، در این وب‌سایت ها پردازش درخواست و لایه Logic وجود ندارد.برای راه اندازی یک وب‌سایت استاتیک نیازی به نوشتن اپلیکیشن سرور نیست. یک وب سرور مانند NGINX می‌تواند نیاز شما را برطرف کند. در زیر کانفیگ NGINX مربوط به یک وب‌سایت استاتیک را مشاهده می‌کنید:server {
    listen 80;
    server_name example.com;
    location / {
        root /web;
        index index.html;
    }
}کانفیگ بالا، تعریف یک سرور (وب‌سایت) در NGINX است. وب‌سایت مورد نظر به پورت 80 و دامنه example.com گوش می‌کند (example.com:80). به ازای هر درخواستی که Path آن با / شروع می‌شود (یعنی تمامی درخواست ها)، NGINX به دنبال فایلی با مسیر مطابق با Path در دایرکتوری web/ می‌گردد، اگر فایل مورد نظر وجود داشت آنرا بعنوان پاسخ به کلاینت می‌دهد، اگر وجود نداشت خطای 404 Not Found را برمی‌گرداند و اگر مسیر مورد نظر یک دایرکتوری باشد نه یک فایل، به دنبال فایلی با نام index.html درون آن دایرکتوری می‌گردد. در زیر لیستی از URL ها و فایل هایی که NGINX به ازای آن بر می‌گرداند را می‌توانید مشاهده کنید.URL: http://example.com/images/the_persistence_of_memory.jpg
Path: /images/the_persistence_of_memory.jpg
Type: File
File: /web/images/the_persistence_of_memory.jpg

URL: http://example.com/images
Path: /images
Type: Directory
File: /web/images/index.html

URL: http://example.com/
Path: /
Type: File
File: /web/index.htmlبیشتر بخوانید:https://en.wikipedia.org/wiki/Static_web_pageوب سایت های PHPاین بخش مخصوص علاقه‌مندانی است که می‌خواهند از زبان PHP برای ساخت اپلیکیشن سمت سرور استفاده کنند.در زبان PHP امکاناتی برای کار با سوکت و هندل کردن درخواست های HTTP وجود دارد اما متاسفانه استفاده از آنها برای سرویس های واقعی (غیر تستی) پیشنهاد نمی‌شود. برای حل این مشکل در کنار PHP از یک وب سرور مانند NGINX یا Apache HTTP Server استفاده می‌شود.کامپایلر PHP در دو نسخه CLI و FPM منتشر می‌شود. نسخه CLI مخصوص نوشتن اپلیکیشن های خط فرمان و نسخه FPM مخصوص نوشتن اپلیکیشن های سرور است و ما در اینجا به نسخه FPM آن نیاز داریم. نسخه FPM بطور پیشفرض به پورت 9000 گوش می‌کند و وب سرور ها با استفاده از این پورت می‌توانند با PHP ارتباط برقرار کنند و فایل های PHP را کامپایل کنند تا خروجی را دریافت و نهایتا به کلاینت بفرستند.برای طراحی یک اپلیکیشن سرور به زبان PHP، فایل های مربوط به کد های PHP را باید یک دایرکتوری در سرور قرار بگیرند. PHP و یک وب‌سرور مانند NGINX و ابزار های مورد نیاز اپلیکیشن نیز باید بر روی سرور نصب شوند.server {
    listen 80;

    root /var/www/example;
    index index.html index.php;

    server_name example.com;

    location / {
        try_files $uri $uri/ =404;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass 127.0.0.1:9000;
    }
}کانفیگ NGINX بالا example.com:80 را ارائه می‌دهد. این کانفیگ مشابه کانفیگ مربوط به وب‌سایت های استاتیک می‌باشد و عینا همان قابلیت ها را به علاوه قابلیت های مربوط به PHP را ارائه می‌دهد. بخش هایی که برای اپلیکیشن PHP به اضافه شده است،‌ یکی جستجوی index.php در کنار index.html به هنگامی که Path درخواست متعلق به یک دایرکتوی است و دیگری پردازش فایل هایی است که پسوند php دارند.در خواست های کلاینت در صورتی که منتهی به فایل های غیر php شوند همانند وب‌سایت های استاتیک، NGINX محتوای فایل مورد نظر را بعنوان پاسخ HTTP برمی‌گرداند. در صورتی که فایل مورد نظر، فایلی با پسوند php باشد، NGINX آدرس فایل را به PHP-FPM نصب شده رو همان سرور (به سوکت 127.0.0.1:9000) میفرستد تا PHP آنرا کامپایل کند و خروجی کد را به NGINX برگرداند. NGINX خروجی PHP را بعنوان پاسخ HTTP به کلاینت برمی‌گرداند.بیشتر بخوانید:https://en.wikipedia.org/wiki/PHPارتباط بین اپلیکیشن های سرورگاهی یک اپلیکیشن سرور جهت ارائه سرویس، به یک اپلیکیشن سرور دیگر (در همان سرور یا یک سرور خارجی) نیازمند است. برای مثال یک اپلیکیشن به وضعیت آب و هوای یک شهر در یک زمان خاص نیاز دارند، در این صورت باید از وب‌سرویس های آب و هوا (اپلیکیشن سرور خارجی) استفاده کند.هنگامی که دو اپلیکیشن سمت سرور با هم ارتباط برقرار می‌کنند، می‌توان مجددا از اصطلاح اپلیکیشن کلاینت برای درخواست کننده و اپلیکیشن سرور برای سرویس دهنده استفاده می‌شود.برای ارتباط بین اپلیکیشن های سرور می‌توان همانند ارتباط بین اپلیکیشن های کلاینت و سرور از API های RESTful استفاده کرد. از دیگر روش های ارتباط می‌توان به پروتکل های Remote Procedure Call (RPC) همانند SOAP یا gRPC که خود بر پایه پروتکل HTTP هستند یا Message Queue ها استفاده کرد.پروتکل SOAP یک پروتکل بر پایه پروتکل ‌HTTP است که برای ارتباط میان دو اپلیکیشن استفاده می‌شود. در این پروتکل از فرمت XML برای انتقال اطلاعات استفاده می‌شود. در زبان های مختلف ماژول های کلاینت و سرور برای آن پیاده سازی شده است. با استفاده از ماژول سرور در اپلیکیشن سرور، می‌توان توابعی را پیاده ‌سازی کرد و با استفاده از ماژول کلاینت در اپلیکیشن کلاینت می‌توان آن توابع را فراخوانی کند. در پروتکل SOAP تلاش گردیده تا اپلیکیشن کلاینت بتواند توابع موجود در اپلیکیشن سرور را به آسانی توابع داخلی خود فراخوانی کند. با این حال، پروتکل SOAP امروزه محبوبیت خود را از دست داده است.پروتکل gRPC نیز بر پایه HTTP (نسخه ۲ و بالاتر) و برای ارتباط بین دو اپلیکیشن طراحی شده است. در این پروتکل برای انتقال اطلاعات از فرمت ProtoBuf استفاده می‌شود. همانند SOAP، در این پروتکل تلاش گردیده تا اپلیکیشن کلاینت بتواند توابع موجود در اپلیکیشن سرور را به آسانی توابع داخلی خود فراخوانی کند.در ارتباط از طریق Message Queue ها از پارادایم Publisher و Subscriber استفاده می‌شود که با روش Request/Response (درخواست و پاسخ) متفاوت است. در این نوع ارتباط، اپلیکیشنی که نقش Publisher را دارد، اطلاعات مربوط به رویدادی که رخ داده شده را منتشر می‌کند، این رویداد در صف (ابزاری مانند Redis Kafka ،NATS ،RabbitMQ و ...) قرار می‌گیرد. از طرف دیگر، اپلیکیشنی که نقش Subscriber را دارد همیشه در حال گوش دادن به صف است تا به محض اینکه رویداد جدیدی رخ داد، اطلاعات آنرا دریافت کند. برای مثال در یک سیستم، یک اپلیکیشن (A) مسئول نام‌نویسی کاربران است و یک اپلیکیشن (B) مسئول فرستادن SMS است. وقتی کاربر جدید نام‌نویسی کند، اپلیکیشن A، اطلاعاتی مانند متن پیام خوشامدگویی و شماره کاربر را در صف منتشر می‌کند. از طرف دیگر، اپلیکیشن B که Subscriber صف می‌باشد، از رویداد جدید باخبر می‌شود و اطلاعات آن را دریافت می‌کند و فرایند ارسال SMS را انجام می‌دهد.بیشتر بخوانید:https://en.wikipedia.org/wiki/SOAPhttps://grpc.iohttps://en.wikipedia.org/wiki/Message_queueسخن پایانیهدف از این مقاله، آشنایی علاقه‌مندان با نحوه اجرای فرایند ها در سرویس های تحت وب (وب سایت ها، وب اپلیکیشن ها، سرویس های کلاینت سرور و ...) به زبانی ساده بود. این مقاله به دلیل پوشش دادن حجم زیادی از مطالب متنوع بسیار خلاصه نوشته شده اما ممکن است در آینده کامل تر شود. در این راستا دیدگاه ها و ایده های شما کمک بزرگی خواهد بود...</description>
                <category>میلاد رحیمی</category>
                <author>میلاد رحیمی</author>
                <pubDate>Tue, 06 Apr 2021 12:53:23 +0430</pubDate>
            </item>
                    <item>
                <title>تحلیل داستان سه قطره خون اثر صادق هدایت</title>
                <link>https://virgool.io/@miladrahimi/%D8%AA%D8%AD%D9%84%DB%8C%D9%84-%D8%AF%D8%A7%D8%B3%D8%AA%D8%A7%D9%86-%D8%B3%D9%87-%D9%82%D8%B7%D8%B1%D9%87-%D8%AE%D9%88%D9%86-%D8%A7%D8%AB%D8%B1-%D8%B5%D8%A7%D8%AF%D9%82-%D9%87%D8%AF%D8%A7%DB%8C%D8%AA-pjn3pp3f5c1z</link>
                <description>چند وقت پیش تحلیل بسیار زیبایی از داستان کوتاه سه قطره خون اثر صادق هدایت لابه‌لای پست های قدیمی فیسبوک پیدا کردم و به نظرم جای درخوری برای این تحلیل (تفسیر) بی‌نظیر نبود. به همین دلیل با ارجاع به منبع اصلی، آنرا اینجا منتشر میکنم تا شاید در دسترس علاقه‌مندان بیشتری قرار بگیرد.اصل داستان سه قطره خون را می توانید از ویکی‌نبشته (لینک داستان سه قطره خون در ویکی‌نبشته) که خودم به تازگی طبق نسخه چاپی ویرایش کردم بخوانید. با کلیک بر دکمه «بارگیری» در ویکی‌نبشته می‌توانید داستان را با فرمت PDF دانلود کنید.تحلیل داستان سه قطره خون از صادق هدایتتحلیل سه قطره خون - صادق هدایتﺩﺭ ﺍﻳﻦ ﻛﻪ ﻣﻴﺮﺯﺍ ﺍﺣﻤﺪ ﺧﺎﻥ ﺩﻳﻮﺍﻧﻪ ﺍﺳﺖ، ﺷﻜﻲ ﻧﻴﺴﺖ. ﺍﻭ ﻛﻪ ﺩﺭ ﺩﺍﺭﺍﻟﻔﻨﻮﻥ ﺩﺭﺱ ﻣﻲ‌ﺧﻮﺍﻧﺪﻩ، ﺍﻛﻨﻮﻥ ﺩﺭ ﺗﻴﻤﺎﺭﺳﺘﺎﻥ ﺍﺳﺖ ﻭ ﻇﺎﻫﺮﺍ ﺑﻪ ﺍﻭ ﻭﻋﺪﻩ ﻣﺮﺧﺼﻲ ﻋﺎﺟﻞ ﺩﺍﺩﻩﺍﻧﺪ. ﺍﻣﺮﻭﺯ ﺑﻪ ﺧﻮﺍﺳﺘﻪ‌ﻱ ﺩﻳﺮﻳﻨﻪ‌ﺍﺵ ﻛﻪ ﻛﺎﻏﺬ ﻭ ﻗﻠﻢ ﺍﺳﺖ، ﭘﺎﺳﺦ ﺩﺍﺩﻩ ﺷﺪﻩ ﻭ ﺍﻛﻨﻮﻥ ﺍﻭ ﻣﺸﻐﻮﻝ ﻧﻮﺷﺘﻦ ﺁﻥ ﭼﻴﺰﻱ ﺍﺳﺖ ﻛﻪ ﻣﺎ ﻣﻲ‌ﺧﻮﺍﻧﻴﻢ. ﺭﺍﻭﻱ ﺍﺯ ﺗﻌﺪﺍﺩﻱ ﺍﺷﺨﺎﺹ ﻭ ﭼﻨﺪ ﻭﺍﻗﻌﻪ ﻳﺎﺩ ﻣﻲ‌ﻛﻨﺪ ﻛﻪ ﺁنﻫﺎ ﺭﺍ ﺑﺮ ﻣﻲﺷﻤﺮﻡ. ﺍﺷﺨﺎﺹ ﻧﺎﻣﺒﺮﺩﻩ ﺍﻳﻦﻫﺎ ﻫﺴﺘﻨﺪ: ﻣﻴﺮﺯﺍ ﺍﺣﻤﺪ ﺧﺎﻥ (ﺭﺍﻭﻱ)، ﻧﺎﻇﻢ، ﺣﺴﻦ، ﻣﺤﻤﺪ ﻋﻠﻲ، ﺩﻛﺘﺮ، ﺻﻐﺮﺍ ﺳﻠﻄﺎﻥ، ﺗﻘﻲ، ﻋﺒﺎﺱ، ﺳﻴﺎﻭﺵ، ﺭﺧﺴﺎﺭﻩ، ﻣﺎﺩﺭ ﺭﺧﺴﺎﺭﻩ ﻭ ﺧﻮﺍﻫﺮ ﺭﺧﺴﺎﺭﻩ ﻛﻪ ﻧﺎﻣﻲ ﺍﺯﺵ ﻫﺴﺖ ﻭ ﺧﻮﺩﺵ ﻧﻴﺴﺖ. ﺑﻌﻀﻲ ﺍﺯ ﺍﻳﻦ ﺍﺷﺨﺎﺹ ﻣﻮﺟﻮﺩﻳﺖ ﻭﺍﻗﻌﻲ ﺧﻮﺩ ﺭﺍ ﺣﻔﻆ ﻣﻲﻛﻨﻨﺪ ﻭ ﺑﻌﻀﻲ ﻭﺍﻗﻌﻴﺖ ﻭﺟﻮﺩﻱ ﺷﺎﻥ ﺗﺤﺖ ﺍﻟﺸﻌﺎﻉ ﺫﻫﻨﻴﺖ ﻣﻴﺮﺯﺍ ﺍﺣﻤﺪ ﺧﺎﻥ ﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ ﻭ ﺑﻴﺸﺘﺮ ﻣﺤﺼﻮﻝ ﺫﻫﻦ ﺍﻭ ﻣﻲﺷﻮﻧﺪ ﺗﺎ ﺁﻧﭽﻪ ﺧﻮﺩ ﻫﺴﺘﻨﺪ. ﺍﻳﻦ ﺩﻭ ﮔﺎﻧﮕﻲ ﻧﻘﺶ ﺩﺭ ﻣﻮﺭﺩ ﺣﻴﻮﺍﻧﺎﺕ ﻭ ﺍﺷﻴﺎ ﻭ ﻣﻜﺎﻥ ﻭ ﺯﻣﺎﻥ ﺩﺍﺳﺘﺎﻥ ﻧﻴﺰ ﻭﺟﻮﺩ ﺩﺍﺭﺩ: ﺩﻭﺗﺎ ﮔﺮﺑﻪ ﻭ ﻳﻚ ﻗﻨﺎﺭﻱ ﻭ ﻳﻚ ﻣﺮﻍ ﺣﻖ، ﺷﺸﻠﻮﻝ، ﺗﺎﺭ، ﺍﺗﺎﻗﻲ ﺁﺑﻲﺭﻧﮓ ﺑﺎ ﻛﻤﺮﻛﺶ ﻛﺒﻮﺩ ﻛﻪ ﺑﻪ ﻋﻨﻮﺍﻥ ﺍﺗﺎﻕ ﺭﺍﻭﻱ ﻫﻢ ﺩﺭ ﺑﻴﻤﺎﺭﺳﺘﺎﻥ، ﻫﻢ ﺩﺭ ﺧﺎﻧﻪﻱ ﺧﻮﺩﺷﺎﻥ ﻭ ﻫﻢ ﺑﻪ ﻋﻨﻮﺍﻥ ﺍﺗﺎﻕ ﺳﻴﺎﻭﺵ ﺗﻜﺮﺍﺭ ﻣﻲﺷﻮﺩ، ﺣﻴﺎﻁ ﺧﺎﻧﻪﻱ ﺳﻴﺎﻭﺵ، ﺣﻴﺎﻁ ﺑﻴﻤﺎﺭﺳﺘﺎﻥ، ﺩﺭﺧﺖ ﻛﺎﺝ ﺧﺎﻧﻪﻱ ﺳﻴﺎﻭﺵ ﻛﻪ ﮔﺮﺑﻪ ﺑﺮ ﺁﻥ ﭘﻨﺎﻩ ﻣﻲﮔﻴﺮﺩ ﻭ ﺩﺭﺧﺖ ﻛﺎﺝ ﺣﻴﺎﻁ ﺑﻴﻤﺎﺭﺳﺘﺎﻥ ﻛﻪ ﻧﺎﻇﻢ ﻗﻔﺲ ﻗﻨﺎﺭﻱ ﺍﺵ ﺭﺍ ﺑﺮ ﺁﻥ ﻣﻲﺁﻭﻳﺰﺩ. ﺍﻣﺎ ﺁﻥ ﻋﺪﻩ ﺍﺷﺨﺎﺻﻲ ﻛﻪ ﻣﻮﺟﻮﺩﻳﺖ ﺷﺎﻥ ﻭﺍﻗﻌﻲ ﺍﺳﺖ ﻭ ﺑﻪ ﻟﻌﺎﺏ ﺫﻫﻦ ﺭﺍﻭﻱ ﺁﻟﻮﺩﻩ ﻧﻤﻲﺷﻮﻧﺪ: ﺣﺴﻦ ﺑﺎ ﺩﻳﮓ ﺍﺷﻜﻨﻪ، ﻣﺤﻤﺪ ﻋﻠﻲ، ﺩﻛﺘﺮ، ﺻﻐﺮﺍ ﺳﻠﻄﺎﻥ ﻭ ﺗﻘﻲ. ﺟﺰ ﺩﻛﺘﺮ ﻭ ﻣﺤﻤﺪ ﻋﻠﻲ، ﺑﺎﻗﻲ ﺩﻳﻮﺍﻧﮕﺎﻧﻲ ﻫﺴﺘﻨﺪ ﻛﻪ ﺭﺍﻭﻱ ﻧﻴﺰ ﺑﻪ ﺩﻳﻮﺍﻧﻪ ﺑﻮﺩﻥ ﺁﻥ ﻫﺎ ﺍﺫﻋﺎﻥ ﺩﺍﺭﺩ ﻭ ﺣﺎﺻﻞ ﻧﮕﺎﻩ ﺑﻴﺮﻭﻧﻲ ﺍﻭ ﻫﺴﺘﻨﺪ ﻭ ﺑﺎ ﺗﺸﺮﻳﺢ ﺁﻥﻫﺎ ﺩﺭ ﻭﺍﻗﻊ ﻣﺤﻴﻂ ﺑﻴﻤﺎﺭﺳﺘﺎﻥ ﺭﺍ ﻣﻲﺳﺎﺯﺩ ﻭ ﺍﺯ ﺍﻳﻦ ﻃﺮﻳﻖ ﻣﺎ ﺩﺭﻣﻲﻳﺎﺑﻴﻢ ﻛﻪ ﺭﺍﻭﻱ ﺩﻳﻮﺍﻧﻪﻱ ﺧﻄﺮﻧﺎﻛﻲ ﺍﺳﺖ ﻛﻪ ﺗﺤﺖ ﻣﻌﺎﻟﺠﺎﺕ ﺷﺪﻳﺪ ﻗﺮﺍﺭ ﺩﺍﺭﺩ ﻳﺎ ﺩﺍﺷﺘﻪ ﻭ ﺍﻛﻨﻮﻥ ﺑﻪ ﻣﺮﺣﻠﻪﺍﻱ ﺭﺳﻴﺪﻩ ﻛﻪ ﺑﺎ ﺑﺮﻭﻥ ﺍﻓﻜﻨﻲ ﺁﻧﭽﻪ ﺍﻭ ﺭﺍ ﺑﻪ ﺗﻴﻤﺎﺭﺳﺘﺎﻥ ﻛﺸﺎﻧﻴﺪﻩ، ﺑﺨﺶ ﭘﻴﺸﺮﻓﺘﻪﺗﺮﻱ ﺍﺯ ﺗﻴﻤﺎﺭ ﺧﻮﻳﺶ ﺭﺍ ﻣﻲﮔﺬﺭﺍﻧﺪ ﻭ ﺑﺮﺍﻱ ﻫﻤﻴﻦ ﺍﺳﺖ ﻛﻪ ﻛﺎﻏﺬ ﻭ ﻗﻠﻢ ﺩﺭ ﺍﺧﺘﻴﺎﺭﺵ ﮔﺬﺍﺷﺘﻪﺍﻧﺪ. ﺑﻪ ﺍﻳﻦ ﺗﺮﺗﻴﺐ ﭘﺎﺳﺦ ﺍﻳﻦ ﺳﻮﺍﻝ ﻛﻪ ﭼﺮﺍ ﭘﻴﺶ ﺍﺯ ﺍﻳﻦ ﺑﻪ ﺍﻭ ﻛﺎﻏﺬ ﻭ ﻗﻠﻢ ﻧﻤﻲﺩﺍﺩﻩﺍﻧﺪ، ﺭﻭﺷﻦ ﻣﻲﺷﻮﺩ. ﭼﻪ ﺑﺴﺎ ﺍﮔﺮ ﻛﺎﻏﺬ ﻭ ﻗﻠﻢ ﺭﺍ ﺯﻭﺩﺗﺮ ﺑﻪ ﺍﻭ ﻣﻲﺩﺍﺩﻧﺪ، ﺑﺎ ﻗﻠﻢ ﺑﻪ ﺧﻮﺩ ﺻﺪﻣﻪ ﻣﻲﺯﺩ ﻳﺎ ﻛﺎﻏﺬﻫﺎ ﺭﺍ ﻣﻲﺧﻮﺭﺩ. ﻣﻀﺎﻓﺎ ﺍﻳﻦ ﻛﻪ ﺗﺸﺮﻳﺢ ﺍﻋﻤﺎﻝ ﺧﻄﺮﻧﺎﻙ ﺩﻳﻮﺍﻧﻪﻫﺎﻱ ﺩﻳﮕﺮ ﻧﺸﺎﻥ ﺁﻥ ﺍﺳﺖ ﻛﻪ ﺭﺍﻭﻱ ﺑﻪ ﻣﺮﺣﻠﻪﺍﻱ ﺍﺯ ﺗﺸﺨﻴﺺ ﺭﺳﻴﺪﻩ ﻛﻪ ﺍﻳﻦ ﮔﻮﻧﻪ ﺍﻋﻤﺎﻝ ﺭﺍ ﺧﻄﻴﺮ ﻣﻲﺑﻴﻨﺪ ﻭ ﺍﻳﻦ ﻳﻌﻨﻲ ﻋﺎﻗﻞﺗﺮ ﺩﻳﺪﻥ ﺧﻮﺩ ﻧﺴﺒﺖ ﺑﻪ ﺁﻧﺎﻥ. ﺍﻭ ﺑﺎ ﺗﻘﺒﻴﺢ ﺭﻓﺘﺎﺭ ﺩﻳﻮﺍﻧﮕﺎﻥ ﻧﺸﺎﻥ ﻣﻲﺩﻫﺪ ﺑﻪ ﺩﺭﺳﺘﻲ ﺭﻓﺘﺎﺭﻱ ﻛﻪ ﺑﺎﻳﺪ ﺻﻮﺭﺕ ﺑﮕﻴﺮﺩ، ﺁﮔﺎﻩ ﺍﺳﺖ، ﻳﻌﻨﻲ ﺑﻪ ﺳﻄﺤﻲ ﺍﺯ ﺧﻮﺩﺁﮔﺎﻫﻲ ﺭﺳﻴﺪﻩ ﻛﻪ ﺑﺮ ﺍﻋﻤﺎﻝ ﺧﻮﺩ ﺗﺎ ﺣﺪﻭﺩ ﺯﻳﺎﺩﻱ ﻣﺴﻠﻂ ﺷﺪﻩ ﻭ ﺷﺎﻳﺪ ﺑﺮﺍﻱ ﻫﻤﻴﻦ ﺍﺳﺖ ﻛﻪ ﻣﻲ ﺧﻮﺍﻫﻨﺪ ﻣﺮﺧﺼﺶ ﻛﻨﻨﺪ، ﭼﻮﻥ ﺩﻭﺭﻩﻱ ﺧﻄﺮﻧﺎﻙ ﺑﻴﻤﺎﺭﻱ ﺭﺍ ﺳﭙﺮﻱ ﻛﺮﺩﻩ ﺍﺳﺖ. ﺍﻳﻦ ﻛﻪ ﺍﻭ ﻣﻲﮔﻮﻳﺪ ﺍﮔﺮ ﻣﻦ ﺟﺎﻱ ﺩﻛﺘﺮ ﺑﻮﺩﻡ، ﺑﻪ ﻫﻤﻪﻱ ﺍﻳﻦ ﺩﻳﻮﺍﻧﻪﻫﺎ ﺯﻫﺮ ﻣﻲﺧﻮﺭﺍﻧﺪﻡ ﻭ ﺑﻌﺪ ﺩﺳﺖ ﺑﻪ ﻛﻤﺮ ﻣﻲﺯﺩﻡ ﻭ ﺑﺮﺩﻧﺸﺎﻥ ﺭﺍ ﺑﺮﺍﻱ ﺩﻓﻦ ﻛﺮﺩﻥ ﺗﻤﺎﺷﺎ ﻣﻲﻛﺮﺩﻡ، ﻧﺎﺷﻲ ﺍﺯ ﺗﺼﻮﺭ ﺳﻼﻣﺖ ﺭﻭﺍﻥ ﺧﻮﺩ ﺩﺭ ﻣﻘﺎﺑﻞ ﺁﻥﻫﺎﺳﺖ. ﺍﻭ ﺑﻪ ﻣﺮﺣﻠﻪﺍﻱ ﺍﺯ ﺑﻬﺒﻮﺩﻱ ﺭﺳﻴﺪﻩ ﻛﻪ ﻓﻜﺮ ﻣﻲﻛﻨﺪ ﺩﻳﻮﺍﻧﻪﻫﺎﻳﻲ ﺩﺭ ﺍﻳﻦ ﺣﺪ ﺯﻧﺪﻩ ﺑﻮﺩﻧﺸﺎﻥ ﻓﺎﻳﺪﻩﺍﻱ ﺑﺮﺍﻱ ﺧﻮﺩﺷﺎﻥ ﻭ ﺑﺮﺍﻱ ﺩﻳﮕﺮﺍﻥ ﻧﺪﺍﺭﺩ، ﺩﻳﻮﺍﻧﻪﻫﺎﻳﻲ ﻛﻪ ﻣﺮﺩﻣﻚ ﭼﺸﻤﺎﻥ ﺧﻮﺩ ﺭﺍ ﻣﻲﺗﺮﻛﺎﻧﻨﺪ ﻳﺎ ﺷﻜﻢ ﺧﻮﺩ ﺭﺍ ﻣﻲﺩﺭﻧﺪ ﻭ ﺑﺎ ﺭﻭﺩﻩﻫﺎﻳﺸﺎﻥ ﺑﺎﺯﻱ ﻣﻲﻛﻨﻨﺪ ﻭ ...، ﺑﻬﺘﺮ ﺍﺳﺖ ﺑﻤﻴﺮﻧﺪ ﻭ ﺑﻼﻓﺎﺻﻠﻪ ﭘﺲ ﺍﺯ ﺍﻳﻦ ﺍﺩﻋﺎ ﻣﻲﮔﻮﻳﺪ ﻣﻦ ﻫﻢ ﺍﻭﺍﻳﻞ ﻛﻪ ﺑﻪ ﺍﻳﻦ ﺟﺎ ﺁﻣﺪﻩ ﺑﻮﺩﻡ، ﻓﻜﺮ ﻣﻲﻛﺮﺩﻡ ﻣﻲﺧﻮﺍﻫﻨﺪ ﺑﺎ ﺧﻮﺭﺍﻧﺪﻥ ﺯﻫﺮ ﺑﻪ ﻣﻦ ﻣﺮﺍ بکشند ﻛﻪ ﺩﻟﻴﻞ ﺍﻳﻦ ﻭﺣﺸﺖ ﺍﻭ ﺭﺍ ﺑﻌﺪﺗﺮ ﺗﻮﺿﻴﺢ ﺧﻮﺍﻫﻢ ﺩﺍﺩ. ﭘﺲ ﻛﺎﺭﻛﺮﺩ ﺍﻳﻦ ﺍﺷﺨﺎﺹ ﻛﻪ ﻓﻘﻂ ﺩﺭ ﻣﻘﺪﻣﻪﻱ ﺩﺍﺳﺘﺎﻥ ﺣﻀﻮﺭ ﺩﺍﺭﻧﺪ، ﻫﻢ ﺑﻪ ﻛﺎﺭ ﺗﻮﺻﻴﻒ ﻣﻮﻗﻌﻴﺖ ﺩﺍﺳﺘﺎﻥ ﺁﻣﺪﻩ ﻫﻢ ﺣﺪ ﻭ ﻣﺮﺯ ﺑﻴﻤﺎﺭﻱ ﺭﺍﻭﻱ ﺭﺍ ﺭﻭﺷﻦ ﻛﺮﺩﻩ ﺍﺳﺖ. ﺍﻣﺎ ﺁﻥ ﺍﺷﺨﺎﺻﻲ ﻛﻪ ﻭﺍﻗﻌﻴﺖ ﺩﺍﺭﻧﺪ ﻳﺎ ﺩﺍﺷﺘﻪﺍﻧﺪ ﻭ ﺩﺭ ﺫﻫﻦ ﺭﺍﻭﻱ ﻛﺎﺭﻛﺮﺩﻱ ﺩﻳﮕﺮ ﻳﺎﻓﺘﻪﺍﻧﺪ، ﺍﺯ ﺍﻳﻦ ﻗﺮﺍﺭﻧﺪ: ﻧﺎﻇﻢ ﺑﻴﻤﺎﺭﺳﺘﺎﻥ، ﻋﺒﺎﺱ، ﺳﻴﺎﻭﺵ، ﺭﺧﺴﺎﺭﻩ، ﻣﺎﺩﺭ ﺭﺧﺴﺎﺭﻩ ﻭ ﺍﺣﺘﻤﺎﻻ ﺧﻮﺍﻫﺮ ﺭﺧﺴﺎﺭﻩ ﻭ ﻧﻴﺰ ﺯﻥ ﻭ ﻣﺮﺩ ﻭ ﺩﺧﺘﺮ ﺟﻮﺍﻧﻲ ﻛﻪ ﺑﻪ ﻣﻼﻗﺎﺕ ﻋﺒﺎﺱ ﻣﻲﺁﻳﻨﺪ. ﺍﻳﻦﻫﺎ ﻛﺴﺎﻧﻲﺍﻧﺪ ﻛﻪ ﺑﻪ ﻟﻌﺎﺏِ ﺫﻫﻦ ﺭﺍﻭﻱ ﻛﻪ ﻣﺤﻞ ﺍﺻﻠﻲ ﺩﺍﺳﺘﺎﻥ ﺍﺳﺖ، ﺁﻏﺸﺘﻪﺍﻧﺪ ﻭ ﺩﺭ ﺻﻮﺭﺗﻲ ﻛﻪ ﺭﺍﻭﻱ ﺑﺘﻮﺍﻧﺪ ﺟﺎﻳﮕﺎﻩ ﻭﺍﻗﻌﻲ ﻫﺮﻳﻚ ﺍﺯ ﺍﻳﻦﻫﺎ ﺭﺍ ﺑﻪ ﻋﻨﻮﺍﻥ ﺍﺷﺨﺎﺹ ﺣﻘﻴﻘﻲ ﺑﻴﺎﺑﺪ، ﻣﺮﺣﻠﻪﻱ ﭘﻴﺸﺮﻓﺘﻪﺗﺮ ﺑﻬﺒﻮﺩﻱ ﺧﻮﻳﺶ ﺭﺍ ﻃﻲ ﺧﻮﺍﻫﺪ ﻛﺮﺩ. ﺫﻫﻦ ﺍﻭ ﺍﻛﻨﻮﻥ ﻋﺒﺎﺱ ﻭ ﺳﻴﺎﻭﺵ ﺭﺍ ﺩﺭ ﻋﻴﻦ ﺭﻓﻴﻖ ﻭ ﻫﻤﺴﺎﻳﻪ ﺑﻮﺩﻥ ﺩﺭ ﻟﺤﻈﺎﺗﻲ ﺑﺎ ﺧﻮﺩ ﻳﻜﻲ ﻣﻲﺑﻴﻨﺪ، ﺑﻪ ﺍﻳﻦ ﺗﺮﺗﻴﺐ ﻛﻪ ﻳﺎ ﺍﻋﻤﺎﻝ ﺧﻮﺩ ﺭﺍ ﺑﻪ ﺁﻥ ﻫﺎ ﻧﺴﺒﺖ ﻣﻲﺩﻫﺪ ﻳﺎ ﺍﻋﻤﺎﻝ ﺁﻥﻫﺎ ﺭﺍ ﻣﺎﻝ ﺧﻮﺩ ﻣﻲﻛﻨﺪ. ﺍﻳﻦ ﺍﺗﻔﺎﻕ ﺍﻭﻟﻴﻦ ﺑﺎﺭ ﺩﺭ ﺩﺍﺳﺘﺎﻥ ﻭﻗﺘﻲ ﻣﻲ ﺍﻓﺘﺪ ﻛﻪ ﺯﻥ ﻭ ﻣﺮﺩ ﻭ ﺩﺧﺘﺮ ﺟﻮﺍﻧﻲ ﺑﻪ ﻣﻼﻗﺎﺕ ﻋﺒﺎﺱ ﺁﻣﺪﻩﺍﻧﺪ. ﻋﺒﺎﺱ ﺧﻮﺩ ﺭﺍ ﺷﺎﻋﺮ ﻭ ﭘﻴﻐﻤﺒﺮ ﻣﻲﺩﺍﻧﺪ ﻭ ﻣﻌﺘﻘﺪ ﺍﺳﺖ ﻛﻪ ﺁﺩﻡ ﺑﻲ ﺑﺨﺖ ﻭ ﺍﻗﺒﺎﻝ ﻋﻼﻣﻪﻱ ﺩﻫﺮ ﻫﻢ ﻛﻪ ﺑﺎﺷﺪ، ﻫﻴﭻ ﻧﻴﺴﺖ. ﻋﺒﺎﺱ ﺗﺎﺭ ﻫﻢ ﻣﻲﺯﻧﺪ ﻭ ﺷﻌﺮﻱ ﺭﺍ ﺩﻛﻠﻤﻪ ﻣﻲﻛﻨﺪ ﻛﻪ ﺩﺭ ﺁﻥ ﻫﻢ ﺍﺯ ﻭﺣﺸﺘﺶ ﺍﺯ ﺷﺐ ﻣﻲﻧﺎﻟﺪ ﻫﻢ ﺍﺯ ﺩﻧﻴﺎﻳﻲ ﻛﻪ ﺟﺰ ﺭﻧﺞ ﻧﻴﺴﺖ ﻭ ﺭﻫﺎﻳﻲ ﺍﺯ ﺁﻥ ﺟﺰ ﺑﺎ ﻣﺮﮒ ﺑﻪ ﺩﺳﺖ ﻧﻤﻲﺁﻳﺪ ﻭ ﺩﻟﻴﻞ ﺍﻳﻦ ﻫﻤﻪ ﺭﺍ ﺳﻪ ﻗﻄﺮﻩ ﺧﻮﻧﻲ ﻣﻲﺩﺍﻧﺪ ﻛﻪ ﺯﻳﺮ ﺩﺭﺧﺖ ﻛﺎﺝ ﺑﺮ ﺯﻣﻴﻦ ﺭﻳﺨﺘﻪ ﺍﺳﺖ. ﺭﺍﻭﻱ ﻣﻌﺘﻘﺪ ﺍﺳﺖ ﺩﺧﺘﺮ ﺟﻮﺍﻧﻲ ﻛﻪ ﻫﻤﺮﺍﻩ ﺯﻥ ﻭ ﻣﺮﺩ ﺑﻪ ﻣﻼﻗﺎﺕ ﻋﺒﺎﺱ ﺁﻣﺪﻩ ﻭ ﮔﻞ ﺁﻭﺭﺩﻩ ﻭ ﺑﻪ ﺍﻭ ﻣﻲﺧﻨﺪﺩ، ﻧﻪ ﺑﻪ ﺧﺎﻃﺮ ﻋﺒﺎﺱ ﻛﻪ ﺑﻪ ﺧﺎﻃﺮ ﺍﻭ ﺁﻣﺪﻩ ﻭ ﻋﺒﺎﺱ ﻛﻪ ﺁﺑﻠﻪﺭﻭ ﻭ ﺯﺷﺖ ﺍﺳﺖ، ﺑﺎ ﺑﻮﺳﻴﺪﻥ ﻳﻮﺍﺷﻜﻲ ﺩﺧﺘﺮ ﺁﻥ ﻫﻢ ﺩﺭ ﭘﻨﺎﻩ ﺩﺭﺧﺖ، ﺑﻪ ﺍﻭ ﻧﺎﺭﻭ ﻣﻲﺯﻧﺪ. ﺭﺍﻭﻱ ﺑﻼﻓﺎﺻﻠﻪ ﺷﺮﻭﻉ ﺑﻪ ﺗﻌﺮﻳﻒ ﻣﺎﺟﺮﺍﻱ ﺧﻮﺩ ﻭ ﺳﻴﺎﻭﺵ ﻣﻲﻛﻨﺪ. ﺍﻭ ﺑﺎ ﺳﻴﺎﻭﺵ ﻫﻤﻜﻼﺱ ﺍﺳﺖ ﻭ ﻫﺮ ﺭﻭﺯ ﺑﺎﻫﻢ ﺍﺯ ﺧﺎﻧﻪ ﺑﻪ ﺩﺍﺭﺍﻟﻔﻨﻮﻥ ﻣﻲﺭﻭﻧﺪ ﻭ ﺑﺎ ﻫﻢ ﺑﺮﻣﻲﮔﺮﺩﻧﺪ ﻭ ﺑﺎ ﻫﻢ ﺩﺭﺱ ﻣﻲﺧﻮﺍﻧﻨﺪ ﻭ ﻣﻮﻗﻊ ﺗﻔﺮﻳﺢ ﻛﻪ ﻣﻲﺷﻮﺩ، ﺭﺍﻭﻱ ﺑﻪ ﺳﻴﺎﻭﺵ ﺗﺎﺭ ﺯﺩﻥ ﻳﺎﺩ ﻣﻲﺩﻫﺪ. ﺭﺧﺴﺎﺭﻩ ﻛﻪ ﺩﺧﺘﺮ ﻋﻤﻮﻱ ﺳﻴﺎﻭﺵ ﻭ ﻧﺎﻣﺰﺩ ﺭﺍﻭﻱ ﺍﺳﺖ، ﻫﻤﻴﺸﻪ ﺑﻪ ﻣﺠﻠﺲ ﺁﻥﻫﺎ ﻣﻲﺁﻳﺪ ﻭ ﻳﻚ ﺑﺎﺭ ﻫﻢ ﻛﻪ ﺣﻀﻮﺭ ﻓﻴﺰﻳﻜﻲ ﺭﺧﺴﺎﺭﻩ ﺭﺍ ﻣﻲﺑﻴﻨﻴﻢ، ﻣﺜﻞ ﺩﺧﺘﺮﻱ ﻛﻪ ﺑﻪ ﻣﻼﻗﺎﺕ ﻋﺒﺎﺱ ﺁﻣﺪﻩ، ﮔﻞ ﺩﺭ ﺩﺳﺖ ﺩﺍﺭﺩ. ﻣﺜﻠﺚ ﺭﺍﻭﻱ، ﺳﻴﺎﻭﺵ ﻭ ﺭﺧﺴﺎﺭﻩ ﺍﻳﻦ ﺟﺎ ﻧﻴﺰ ﺗﻜﺮﺍﺭ ﻣﻲﺷﻮﺩ. ﺑﺎ ﺍﻳﻦ ﺗﻔﺎﻭﺕ ﻛﻪ ﺍﻳﻦ ﺟﺎ ﺭﺍﻭﻱ ﺭﺧﺴﺎﺭﻩ ﺭﺍ ﺑﻲ ﺑﺮﻭ ﺑﺮﮔﺮﺩ ﻣﺘﻌﻠﻖ ﺑﻪ ﺧﻮﺩ ﻣﻲﺩﺍﻧﺪ. ﭘﺲ ﺭﺍﻭﻱ ﺩﺭ ﻳﻚ ﺑﺪﻩﺑﺴﺘﺎﻥ ﺩﺍﺋﻤﻲ ﺑﺎ ﻛﺴﺎﻧﻲ ﺍﺳﺖ ﻛﻪ ﺩﺭ ﺍﻃﺮﺍﻑ ﺍﻭ ﺯﻧﺪﮔﻲ ﻣﻲﻛﻨﻨﺪ ﻭ ﺍﻭ ﻫﺮ ﺑﺎﺭ ﺑﻪ ﺩﻟﻴﻠﻲ ﺑﺨﺸﻲ ﺍﺯ ﻋﻤﻠﻜﺮﺩ ﻭ ﺩﺍﺭﺍﻳﻲ ﻫﺎﻱ ﺧﻮﻳﺶ ﺭﺍ ﺑﻪ ﺁﻥﻫﺎ ﻧﺴﺒﺖ ﻣﻲﺩﻫﺪ ﻭ ﺑﺨﺸﻲ ﺍﺯ ﻋﻤﻠﻜﺮﺩ ﻭ ﺩﺍﺭﺍﻳﻲ ﺁﻥﻫﺎ ﺭﺍ ﻣﺘﻌﻠﻖ ﺑﻪ ﺧﻮﺩ ﻣﻲﻛﻨﺪ. ﻋﺒﺎﺱ ﺑﺮﺍﻱ ﺭﺍﻭﻱ ﺗﺎﺭ ﻣﻲﺯﻧﺪ ﻭ ﺷﻌﺮ ﻣﻲﺧﻮﺍﻧﺪ. ﺭﺍﻭﻱ ﻫﻢ ﺑﺮﺍﻱ ﺳﻴﺎﻭﺵ ﻭ ﺭﺧﺴﺎﺭﻩ ﻭ ﻣﺎﺩﺭ ﺭﺧﺴﺎﺭﻩ ﺗﺎﺭ ﻣﻲﺯﻧﺪ ﻭ ﻫﻤﺎﻥ ﺷﻌﺮﻱ ﺭﺍ ﺑﺮﺍﻱ ﺁﻥﻫﺎ ﻣﻲﺧﻮﺍﻧﺪ ﻛﻪ ﻋﺒﺎﺱ ﺑﺮﺍﻱ ﺍﻭ ﺧﻮﺍﻧﺪﻩ. ﺭﺍﻭﻱ ﺣﺘﻲ ﺑﻪ ﺳﻴﺎﻭﺵ ﻣﺸﻖ ﺗﺎﺭ ﻫﻢ ﻣﻲﺩﻫﺪ، ﻳﻌﻨﻲ ﺩﺭ ﺁﻥ ﺣﺪ ﺗﺎﺭ ﺯﺩﻥ ﺑﻠﺪ ﺍﺳﺖ ﻛﻪ ﺗﺪﺭﻳﺲ ﻫﻢ ﺑﻜﻨﺪ. ﺭﺧﺴﺎﺭﻩ ﻫﻤﺎﻥ ﻃﻮﺭ ﻛﻪ ﺩﺧﺘﺮ ﻋﻤﻮﻱ ﺳﻴﺎﻭﺵ ﺍﺳﺖ، ﻧﺎﻣﺰﺩ ﺭﺍﻭﻱ ﺍﺳﺖ، ﻋﻴﻦ ﺍﻳﻦ ﻣﻄﻠﺐ ﺩﺭ ﻣﻮﺭﺩ ﻋﺒﺎﺱ ﻭ ﺩﺧﺘﺮﻱ ﻛﻪ ﺑﻪ ﻣﻼﻗﺎﺗﺶ ﺁﻣﺪﻩ، ﺻﺎﺩﻕ ﺍﺳﺖ. ﺭﺍﻭﻱ ﻣﻌﺘﻘﺪ ﺍﺳﺖ ﺩﺧﺘﺮ ﻧﻪ ﺑﻪ ﺩﻳﺪﻥ ﻋﺒﺎﺱ ﻛﻪ ﺑﻪ ﺩﻳﺪﻥ ﺍﻭ ﺁﻣﺪﻩ ﻭ ﺩﺳﺘﻪ ﮔﻠﻲ ﺭﺍ ﻫﻢ ﻛﻪ ﺁﻭﺭﺩﻩ، ﻧﻪ ﺑﺮﺍﻱ ﻋﺒﺎﺱ ﻛﻪ ﺑﺮﺍﻱ ﺍﻭﺳﺖ. ﺗﻮﺟﻪ ﻛﻨﻴﻢ ﻛﻪ ﺭﺍﻭﻱ ﭼﻪ ﭼﻴﺰﻫﺎﻳﻲ ﺍﺯ ﺩﻳﮕﺮﺍﻥ ﻣﻲﮔﻴﺮﺩ ﻭ ﭼﻪ ﭼﻴﺰﻫﺎﻳﻲ ﺑﻪ ﺩﻳﮕﺮﺍﻥ ﻣﻲﺩﻫﺪ. ﺍﺯ ﻭﺟﻮﺩ ﺭﺍﻭﻱ ﻭ ﻋﺒﺎﺱ ﻭ ﺩﺧﺘﺮ ﻣﻼﻗﺎﺗﻲ ﻭ ﻧﻴﺰ ﺭﺍﻭﻱ ﻭ ﺳﻴﺎﻭﺵ ﻭ ﺭﺧﺴﺎﺭﻩ ﭘﻲ ﺑﻪ ﻳﻚ ﻣﺜﻠﺚ ﻋﺸﻘﻲ ﻣﻲﺑﺮﻳﻢ ﻛﻪ ﺩﻟﻴﻞ ﺟﻨﻮﻥ ﺭﺍﻭﻱ ﺭﺍ ﺩﺭ ﻫﻤﻴﻦ ﺑﺎﻳﺪ ﺟﺴﺖ. ﻫﻤﺎﻥ ﻃﻮﺭ ﻛﻪ ﺭﺍﻭﻱ ﺩﺧﺘﺮ ﺟﻮﺍﻧﻲ ﺭﺍ ﻛﻪ ﺑﻪ ﻣﻼﻗﺎﺕ ﻋﺒﺎﺱ ﺁﻣﺪﻩ ﺑﻪ ﺧﻮﺩ ﻧﺴﺒﺖ ﻣﻲﺩﻫﺪ، ﺭﺧﺴﺎﺭﻩ ﺭﺍ ﻫﻢ ﻛﻪ ﺩﺧﺘﺮ ﻋﻤﻮﻱ ﺳﻴﺎﻭﺵ ﺍﺳﺖ ﻭ ﻧﺎﻣﺰﺩ ﺳﻴﺎﻭﺵ، ﺑﻪ ﺧﻮﺩ ﻧﺴﺒﺖ ﻣﻲﺩﻫﺪ. ﻣﺎ ﻫﻴﭻ ﻭﻗﺖ ﺍﺛﺮﻱ ﺍﺯ ﺧﻮﺍﻫﺮ ﺭﺧﺴﺎﺭﻩ ﻛﻪ ﺑﻪ ﻇﺎﻫﺮ ﻧﺎﻣﺰﺩ ﺳﻴﺎﻭﺵ ﺍﺳﺖ، ﻧﻤﻲﺑﻴﻨﻴﻢ، ﺣﺘﻲ ﺯﻣﺎﻧﻲ ﻛﻪ ﺳﻴﺎﻭﺵ ﻣﺮﻳﺾ ﺍﺳﺖ، ﺍﻳﻦ ﺭﺧﺴﺎﺭﻩ ﺍﺳﺖ ﻛﻪ ﺑﺎ ﺩﺳﺘﻪﺍﻱ ﮔﻞ ﺑﻪ ﺧﺎﻧﻪﻱ ﺳﻴﺎﻭﺵ ﻣﻲﺁﻳﺪ ﻫﻤﭽﻨﺎﻥ ﻛﻪ ﻓﻘﻂ ﺭﺧﺴﺎﺭﻩ ﺍﺳﺖ ﻛﻪ ﺑﻪ ﻣﺠﻠﺲ ﺗﻔﺮﻳﺢ ﺳﻴﺎﻭﺵ ﻭ ﺭﺍﻭﻱ ﻣﻲﺁﻳﺪ. ﺩﺭ ﻭﺍﻗﻊ ﺧﻮﺍﻫﺮ ﺭﺧﺴﺎﺭﻩ ﺁﺭﺯﻭﻳﻲ ﺍﺳﺖ ﻛﻪ ﺭﺍﻭﻱ ﺩﺍﺭﺩ، ﻛﻪ ﺍﮔﺮ ﭼﻨﻴﻦ ﺧﻮﺍﻫﺮﻱ ﻣﻲﺑﻮﺩ، ﺑﺴﻴﺎﺭﻱ ﺍﺯ ﻣﺸﻜﻼﺕ ﭘﻴﺶ ﺁﻣﺪﻩ ﭘﻴﺶ ﻧﻤﻲﺁﻣﺪ ﻭ ﺭﺍﻭﻱ ﻛﻪ ﺩﺳﺘﺶ ﺩﺭ ﺑﺪﻩﺑﺴﺘﺎﻧﻲ ﺑﺎﺯ ﺍﺳﺖ، ﺧﻴﻠﻲ ﺭﺍﺣﺖ ﺧﻮﺍﻫﺮ ﺭﺧﺴﺎﺭﻩ ﺭﺍ ﺑﻪ ﺳﻴﺎﻭﺵ ﻣﻲﺑﺨﺸﻴﺪ ﻭ ﺧﻮﺩ ﺭﺧﺴﺎﺭﻩ ﺭﺍ ﺗﺼﺎﺣﺐ ﻣﻲﻛﺮﺩ. ﭘﺲ ﺭﺍﻭﻱ ﺭﺧﺴﺎﺭﻩ ﺭﺍ ﺍﺯﺁﻥ ﺧﻮﺩ ﻣﻲﻛﻨﺪ ﻫﻤﺎﻥ ﻃﻮﺭ ﻛﻪ ﺩﺧﺘﺮ ﻣﻼﻗﺎﺗﻲ ﺭﺍ ﺍﺯﺁﻥ ﺧﻮﺩ ﻣﻲﻛﻨﺪ. ﺳﻴﺎﻭﺵ ﻭ ﻋﺒﺎﺱ ﻫﺮ ﺩﻭ ﺩﺳﺖ ﺑﻪ ﻳﻚ ﻛﺎﺭ ﻣﻲﺯﻧﻨﺪ ﻭ ﺁﻥ ﺑﻮﺳﻴﺪﻥ ﺩﺧﺘﺮ ﻫﺎﻳﻲ ﺍﺳﺖ ﻛﻪ ﺭﺍﻭﻱ ﺁﻥﻫﺎ ﺭﺍ ﺑﻪ ﺧﻮﺩ ﻣﺘﻌﻠﻖ ﻣﻲﺩﺍﻧﺪ. ﺭﺍﻭﻱ ﺯﺷﺘﻲ ﭼﻬﺮﻩﻱ ﺧﻮﺩ ﺭﺍ ﻛﻪ ﺁﺑﻠﻪﮔﻮﻥ ﺍﺳﺖ ﻭ ﺑﺎ ﺁﻥ ﻧﻤﻲﺗﻮﺍﻧﺪ ﻣﻮﺭﺩ ﺗﻮﺟﻪ ﻭﺍﻗﻊ ﺷﻮﺩ، ﺑﻪ ﻋﺒﺎﺱ ﻣﻲﺩﻫﺪ ﻭ ﭼﻬﺮﻩﻱ ﺍﻭ ﺭﺍ ﺍﺯﺁﻥ ﺧﻮﺩ ﻣﻲﻛﻨﺪ ﻭ ﺩﺭ ﻋﻮﺽ ﺷﺎﻋﺮﻳﺖ ﻭ ﺗﺎﺭﺯﻧﻲ ﺭﺍ ﻛﻪ ﻣﺎﻝ ﺧﻮﺩ ﺍﺳﺖ، ﺑﻪ ﻋﺒﺎﺱ ﻣﻲﺩﻫﺪ. ﺍﻣﺎ ﺩﺭ ﻛﻨﺎﺭ ﺳﻴﺎﻭﺵ ﻛﻪ ﻗﺮﺍﺭ ﻣﻲﮔﻴﺮﺩ ، ﺑﻴﻤﺎﺭﻱ ﺧﻮﺩ ﺭﺍ ﺑﻪ ﺍﻭ ﻣﻲﺩﻫﺪ ﻭ ﺩﺭ ﻋﻮﺽ ﺭﺧﺴﺎﺭﻩ ﺭﺍ ﺍﺯ ﺍﻭ ﻣﻲﮔﻴﺮﺩ، ﺯﻳﺮﺍ ﺍﻭ ﻋﺎﺷﻖ ﺭﺧﺴﺎﺭﻩ ﺍﺳﺖ، ﺍﻣﺎ ﭼﻮﻥ ﺯﺷﺖ ﺍﺳﺖ، ﻣﻮﺭﺩ ﻗﺒﻮﻝ ﻭ ﺗﻮﺟﻪ ﺭﺧﺴﺎﺭﻩ ﻧﻴﺴﺖ. ﭘﺲ ﺍﻳﻦ ﻋﺸﻖ ﻳﻚ ﻃﺮﻓﻪ ﺍﺳﺖ. ﮔﺮﺑﻪ ﻧﻪ ﻣﺘﻌﻠﻖ ﺑﻪ ﺳﻴﺎﻭﺵ ﻛﻪ ﻣﺘﻌﻠﻖ ﺑﻪ ﺭﺍﻭﻱ ﺍﺳﺖ ﻭ ﻫﻤﻪﻱ ﺁﻧﭽﻪ ﺳﻴﺎﻭﺵ ﺍﺯ ﻧﺎﺯﻱ ﺑﻪ ﺷﺮﺡ ﻭ ﺗﻔﺼﻴﻞ ﻣﻲﮔﻮﻳﺪ، ﺁﻥ ﭼﻴﺰﻱ ﺍﺳﺖ ﻛﻪ ﺭﺍﻭﻱ ﺑﻪ ﺳﻴﺎﻭﺵ ﻣﻨﺘﻘﻞ ﻣﻲﻛﻨﺪ، ﺯﻳﺮﺍ ﺍﻭﺳﺖ ﻛﻪ ﻧﺎﺯﻱ ﺭﺍ ﺟﺎﻳﮕﺰﻳﻦ ﻋﺸﻖ ﺯﻧﺎﻧﻪﺍﻱ ﻛﺮﺩﻩ ﻛﻪ ﺍﺯ ﺁﻥ ﻣﺤﺮﻭﻡ ﺍﺳﺖ. عشق‌بازی ﻧﺎﺯﻱ ﺑﺎ ﮔﺮﺑﻪﻱ ﻧﺮ ﻛﻪ ﺧﻮﺍﺏ ﺍﻭ ﺭﺍ ﻭ ﺩﺭ ﻭﺍﻗﻊ ﺁﺭﺍﻣﺶ ﺍﻭ ﺭﺍ ﮔﺮﻓﺘﻪ ﺍﺳﺖ، ﻣﻐﺎﺯﻟﻪﻱ ﺭﺧﺴﺎﺭﻩ ﺑﺎ ﺳﻴﺎﻭﺵ ﺍﺳﺖ ﻛﻪ ﺍﻭ ﺷﺎﻫﺪ ﻋﺸﻖﻭﺭﺯﻱ ﻭ ﺍﺯﺩﻭﺍﺝ ﺁﻥﻫﺎﺳﺖ، ﺍﺯﺩﻭﺍﺟﻲ ﻛﻪ ﺧﺒﺮﺵ ﺍﻭ ﺭﺍ ﺑﻴﻤﺎﺭ ﻣﻲﻛﻨﺪ، ﺁﻥ ﻗﺪﺭ ﻛﻪ ﺣﻜﻴﻢ ﻫﺮ ﻧﻮﻉ ﻣﻼﻗﺎﺗﻲ ﺭﺍ ﺑﺎ ﺍﻭ ﻣﻤﻨﻮﻉ ﻣﻲﻛﻨﺪ. ﺍﺯﺩﻭﺍﺝ ﺳﻴﺎﻭﺵ ﻭ ﺭﺧﺴﺎﺭﻩ ﺳﺮ ﻣﻲﮔﻴﺮﺩ ﻭ ﺭﺍﻭﻱ ﺍﺯ ﺑﺎﻡ ﺧﺎﻧﻪ ﻛﻪ ﺑﺮ ﺧﺎﻧﻪﻱ ﺳﻴﺎﻭﺵ ﻣﺸﺮﻑ ﺍﺳﺖ، ﻫﺮ ﺷﺐ ﺍﺯ ﺗﺼﻮﺭ ﻋﺸﻖﺑﺎﺯﻱ ﻋﺮﻭﺱ ﻭ ﺩﺍﻣﺎﺩ ﺭﻧﺞ ﻣﻲﻛﺸﺪ، ﺗﺼﻮﺭﻱ ﻛﻪ ﺩﺭ ﻋﺸﻖﺑﺎﺯﻱ ﻧﺎﺯﻱ ﺑﺎ ﺟﻔﺘﺶ ﺗﺠﺴﻢ ﻣﻲﻳﺎﺑﺪ ﻭ ﺭﺍﻭﻱ ﺭﺍ ﻛﻪ ﺍﺯ ﺷﺪﺕ ﻏﻢ ﻭ ﺣﺴﺎﺩﺕ ﺑﻪ ﺟﻨﻮﻥ ﺭﺳﻴﺪﻩ، ﺑﻪ ﻛﺸﺘﻦ ﺟﻔﺖ ﻧﺎﺯﻱ ﻭﺍ ﻣﻲﺩﺍﺭﺩ، ﻳﻌﻨﻲ ﺳﻴﺎﻭﺵ ﺭﺍ ﺩﺭ ﭘﻲ ﺟﻨﻮﻧﻲ ﻛﻪ ﺑﻪ ﺁﻥ ﮔﺮﻓﺘﺎﺭ ﺁﻣﺪﻩ، ﺑﺎ ﺷﺸﻠﻮﻝ ﻣﻲﻛﺸﺪ ﻭ ﺭﻗﻴﺐ ﺭﺍ ﺍﺯ ﺳﺮ ﺭﺍﻩ ﺑﺮ ﻣﻲﺩﺍﺭﺩ. ﺍﮔﺮ ﻣﻲ ﮔﻮﻳﺪ ﺳﻴﺎﻭﺵ ﺁﺧﺮﻳﻦ ﻛﺴﻲ ﺍﺳﺖ ﻛﻪ ﺑﻪ ﻋﻴﺎﺩﺗﻢ ﺁﻣﺪﻩ، ﻧﻈﺮ ﺑﻪ ﺯﻣﺎﻧﻲ ﺩﺍﺭﺩ ﻛﻪ ﺭﺍﻭﻱ ﺧﻮﺩ ﺑﻪ ﺳﻮﻱ ﮔﺮﺑﻪ ﺷﻠﻴﻚ ﻛﺮﺩﻩ ﻭ ﺳﻴﺎﻭﺵ ﺩﺭ ﭘﻲ ﺷﻨﻴﺪﻥ ﺻﺪﺍﻱ ﺗﻴﺮ ﺑﻪ ﺑﺎﻡ ﺁﻣﺪﻩ ﻭ ﺭﺍﻭﻱ ﺭﺍ ﻛﻪ ﺑﺎ ﭘﻴﮋﺍﻣﻪ ﺩﺭ ﺣﻴﺎﻁ ﺍﻳﺴﺘﺎﺩﻩ، ﻣﻲﺑﻴﻨﺪ ﻭ ﺣﺎﻝ ﺍﻭ ﺭﺍ ﻣﻲﭘﺮﺳﺪ ﻭ ﺩﺭ ﭘﺎﺳﺦ ﺑﻪ ﮔﻠﻪﻱ ﺭﺍﻭﻱ ﻛﻪ ﻣﻲﭘﺮﺳﺪ ﭼﺮﺍ ﺑﻪ ﻣﻦ ﺳﺮ ﻧﺰﺩﻱ، ﻣﻲﮔﻮﻳﺪ ﻣﻲﺧﻮﺍﺳﺘﻢ، ﺍﻣﺎ ﺣﻜﻴﻢ ﻗﺪﻏﻦ ﻛﺮﺩﻩ ﺑﻮﺩ. ﺩﺭ ﻭﺍﻗﻊ ﺍﻭ ﻣﺎﺟﺮﺍﻳﻲ ﺭﺍ ﻛﻪ ﺍﺯ ﻗﻮﻝ ﺧﻮﺩ ﺗﻌﺮﻳﻒ ﻣﻲﻛﻨﺪ، ﺁﻥ ﭼﻴﺰﻱ ﺍﺳﺖ ﻛﻪ ﺍﺯ ﺳﻴﺎﻭﺵ ﺷﻨﻴﺪﻩ ﻭ ﺍﻛﻨﻮﻥ ﺁﻥ ﺭﺍ ﺍﺯ ﺁﻥ ﺧﻮﺩ ﻛﺮﺩﻩ ﺍﺳﺖ. ﺗﻮﺻﻴﻔﻲ ﺭﺍ ﻛﻪ ﺑﻪ ﺍﺗﺎﻕ ﺳﻴﺎﻭﺵ ﻧﺴﺒﺖ ﻣﻲﺩﻫﺪ، ﺭﻧﮓ ﺁﺑﻲ ﻭ ﺩﻳﻮﺍﺭﻱ ﻛﻪ ﺗﺎ ﻛﻤﺮﻛﺶ ﺁﻥ ﻛﺒﻮﺩ ﺍﺳﺖ، ﺷﺸﻠﻮﻟﻲ ﻛﻪ ﺳﻴﺎﻭﺵ ﺍﺯ ﺗﻮﻱ ﻛﺸﻮ ﺑﺮ ﻣﻲﺩﺍﺭﺩ ﻭ ﺟﺰﻭﻩ ﻫﺎﻱ ﺩﺭﺳﻲ ﻛﻪ ﺭﻭﻱ ﻣﻴﺰ ﺭﻳﺨﺘﻪ ﺷﺪﻩ ﻭ ...، ﻫﻤﻪ ﻣﺮﺑﻮﻁ ﺑﻪ ﺍﺗﺎﻕ ﺧﻮﺩ ﺍﻭﺳﺖ. ﺍﺯ ﻃﺮﻓﻲ ﻭﻗﺘﻲ ﺭﺧﺴﺎﺭﻩ ﻭ ﻣﺎﺩﺭﺵ ﺳﺮ ﻣﻲﺭﺳﻨﺪ، ﺭﺍﻭﻱ ﺍﺯ ﺯﺑﺎﻥ ﺳﻴﺎﻭﺵ ﻗﺎﺑﻠﻴﺖ ﻫﺎﻱ ﺧﻮﺩ ﺭﺍ ﺷﺮﺡ ﻣﻲﺩﻫﺪ ﺗﺎ ﻣﮕﺮ ﺗﻮﺟﻪ ﺭﺧﺴﺎﺭﻩ ﺭﺍ ﻛﻪ ﺩﺭ ﺍﺻﻞ ﺑﻪ ﺳﻴﺎﻭﺵ ﻋﻼﻗﻪﻣﻨﺪ ﺍﺳﺖ، ﺟﻠﺐ ﻛﻨﺪ، ﺍﻣﺎ ﺭﺧﺴﺎﺭﻩ ﺑﺎ ﺩﻳﻮﺍﻧﻪ ﺧﻮﺍﻧﺪﻥ ﺭﺍﻭﻱ ﻭ ﭘﻨﺎﻩ ﺑﺮﺩﻥ ﺑﻪ ﺁﻏﻮﺵ ﺳﻴﺎﻭﺵ ﺭﺍﻭﻱ ﺭﺍ ﺑﻪ ﺍﻳﻦ ﻧﺘﻴﺠﻪ ﻣﻲﺭﺳﺎﻧﺪ ﻛﻪ ﺑﺮﺍﻱ ﺑﻪ ﭼﺸﻢ ﻣﻌﺸﻮﻕ ﺁﻣﺪﻥ ﺭﺍﻫﻲ ﺟﺰ ﺍﻳﻦ ﻧﺪﺍﺭﺩ ﻛﻪ ﺭﻗﻴﺐ ﺭﺍ ﺍﺯ ﺳﺮ ﺭﺍﻩ ﺑﺮﺩﺍﺭﺩ. ﺍﻣﺎ ﻣﺮﮒ ﺳﻴﺎﻭﺵ ﻭﺍﻗﻌﻲ ﻧﻪ ﺗﻨﻬﺎ ﺭﺍﻭﻱ ﺭﺍ ﺑﻪ ﻣﻌﺸﻮﻕ ﻧﻤﻲﺭﺳﺎﻧﺪ، ﺑﻠﻜﻪ ﻧﺰﺩﻳﻚ ﺗﺮﻳﻦ ﺩﻭﺳﺖ ﺭﺍ ﻧﻴﺰ ﺍﺯ ﺍﻭ ﻣﻲ ﮔﻴﺮﺩ، ﺩﻭﺳﺘﻲ ﻛﻪ ﻏﻢ ﺍﻭ ﺭﺍ ﻣﻲﺧﻮﺭﺩﻩ ﻭ ﻳﺎﺭ ﻏﺎﺭ ﺍﻭ ﺑﻮﺩﻩ. ﭘﺲ ﺍﻭ ﺩﻭ ﺳﺎﻕ ﻣﺜﻠﺚ ﺭﺍ ﺍﺯ ﺩﺳﺖ ﻣﻲﺩﻫﺪ ﻭ ﺗﻚ ﻣﻲﺍﻓﺘﺪ ﻭ ﺑﺮﺍﻱ ﺟﺒﺮﺍﻥ ﺩﻭ ﺳﺎﻕ ﺍﺯ ﺩﺳﺖ ﺩﺍﺩﻩﻱ ﻣﻮﺟﻮﺩﻳﺖ ﺭﻭﺍﻧﻲ ﺧﻮﻳﺶ ﺑﻪ ﻃﻮﺭ ﻏﺮﻳﺰﻱ ﺑﺮﺍﻱ ﺣﻔﻆ ﺧﻮﺩ ﻭ ﺑﺮﺍﻱ ﺟﻠﻮﮔﻴﺮﻱ ﺍﺯ ﻓﺮﻭﭘﺎﺷﻴﺪﮔﻲ ﻫﺮﭼﻪ ﺑﻴﺸﺘﺮ، ﺳﻴﺎﻭﺵ ﻭ ﺭﺧﺴﺎﺭﻩ ﺭﺍ ﺑﻪ ﻭﺟﻮﺩ ﺩﻳﮕﺮﺍﻥ ﻣﻨﺘﻘﻞ ﻣﻲﻛﻨﺪ ﻭ ﺑﺎ ﺗﺨﻴﻞ ﻛﺮﺩﻥ ﺧﻮﺩ ﺭﺍ ﺑﻪ ﺩﻭ ﺳﺎﻕ ﺩﻳﮕﺮ ﻣﺜﻠﺚ ﻭﺟﻮﺩﺵ ﻣﺘﺼﻞ ﻣﻲﻛﻨﺪ ﻛﻪ ﺍﮔﺮ ﻏﻴﺮ ﺍﺯ ﺍﻳﻦ ﻋﻤﻞ ﻣﻲﻛﺮﺩ، ﺩﻧﻴﺎ ﺑﺮﺍﻳﺶ ﻏﻴﺮ ﻗﺎﺑﻞ ﺗﺤﻤﻞ ﻭ ﺑﻪ ﺷﺪﺕ ﻧﺎﺍﻣﻦ ﻣﻲﺷﺪ، ﭼﻨﺎﻥ ﻛﻪ ﺍﻭﺍﻳﻞ ﻭﺭﻭﺩ ﺑﻪ ﺗﻴﻤﺎﺭﺳﺘﺎﻥ ﺗﺼﻮﺭ ﻣﻲﻛﻨﺪ ﻫﻤﻪ ﺩﺭ ﭘﻲ ﺁﻧﻨﺪ ﻛﻪ ﺑﺎ ﺯﻫﺮ ﺭﻳﺨﺘﻦ ﺩﺭ ﻏﺬﺍﻳﺶ ﺍﺯ ﺍﻭ ﺍﻧﺘﻘﺎﻡ ﺧﻮﻥ ﺳﻴﺎﻭﺵ ﺭﺍ ﺑﮕﻴﺮﻧﺪ. ﺭﺍﻭﻱ ﻭﺟﺪﺍﻥ ﻣﻌﺬﺏ ﺧﻮﺩ ﺭﺍ ﺑﻪ ﺑﻴﺮﻭﻥ ﺍﺯ ﺧﻮﺩ ﻭ ﺑﻪ ﻧﺎﻇﻢ ﻣﻨﺘﻘﻞ ﻣﻲﻛﻨﺪ ﻭ ﺑﻪ ﺍﻳﻦ ﺗﺮﺗﻴﺐ ﺧﻮﺩ ﺭﺍ ﺩﺭ ﭘﻨﺎﻩ ﻗﺪﺭﺕ ﻧﺎﻇﻢ ﻛﻪ ﻭﻇﻴﻔﻪﻱ ﺍﻳﺠﺎﺩ ﻧﻈﻢ ﺩﺭ ﺗﻴﻤﺎﺭﺳﺘﺎﻥ ﺭﺍ ﺑﻪ ﻋﻬﺪﻩ ﺩﺍﺭﺩ، ﻗﺮﺍﺭ ﻣﻲﺩﻫﺪ ﻭ ﻛﺸﺘﻦ ﮔﺮﺑﻪﺍﻱ ﺭﺍ ﻛﻪ ﺷﺐﻫﺎﻱ ﺍﻭ ﺭﺍ ﻛﺎﺑﻮﺳﻨﺎﻙ ﻛﺮﺩﻩ ﻭ ﺩﺭ ﭘﻲ ﺍﻧﺘﻘﺎﻡ ﻛﺸﻲ ﺍﺯ ﺍﻭﺳﺖ، ﺑﻪ ﻋﻬﺪﻩﻱ ﻧﺎﻇﻢ ﻣﻲﮔﺬﺍﺭﺩ. ﺍﻛﻨﻮﻥ ﻧﺎﻇﻢ ﻭﻇﻴﻔﻪﺍﻱ ﺟﺰ ﺍﻳﻦ ﻧﺪﺍﺭﺩ ﻛﻪ ﻛﻠﻚ ﮔﺮﺑﻪﺍﻱ ﺭﺍ ﺑﻜﻨﺪ ﻛﻪ ﺟﻔﺘﺶ ﺭﺍ ﺭﺍﻭﻱ ﻛﺸﺘﻪ، ﺟﻔﺘﻲ ﻛﻪ ﺩﺭ ﻣﻌﺼﻮﻣﻴﺖ ﻛﻢ ﺍﺯ ﻗﻨﺎﺭﻱ ﻧﺪﺍﺷﺘﻪ ﻭ ﺑﻪ ﻧﺎﺣﻖ ﻛﺸﺘﻪ ﺷﺪﻩ ﻭ ﺩﺭ ﻭﺍﻗﻊ ﻗﺮﺑﺎﻧﻲ ﻣﺜﻠﺚ ﻋﺸﻖ ﺧﻮﺩ ﻭ ﺭﺧﺴﺎﺭﻩ ﻭ ﺭﺍﻭﻱ ﺍﺳﺖ. ﺍﻭ ﻣﺮﻍ ﺣﻘﻲ ﺍﺳﺖ ﻛﻪ ﻋﺪﺍﻟﺖ ﺭﺍ ﻓﺮﻳﺎﺩ ﻣﻲﺯﻧﺪ ﻭ ﺑﺮﺍﻱ ﺁﻥ ﻛﻪ ﺍﻧﺘﻘﺎﻡ ﻣﺮﮒ ﻧﺎﺟﻮﺍﻧﻤﺮﺩﺍﻧﻪﻱ ﺧﻮﺩ ﺭﺍ ﺍﺯ ﺭﺍﻭﻱ ﺑﮕﻴﺮﺩ، ﺍﻭ ﺭﺍ ﺭﺍﺣﺖ ﻧﻤﻲﮔﺬﺍﺭﺩ ﻭ ﻫﺮ ﺷﺐ ﺁﻥ ﻗﺪﺭ ﻓﺮﻳﺎﺩ ﻣﻲﻛﺸﺪ ﺗﺎ ﺳﻪ ﻗﻄﺮﻩ ﺧﻮﻥ ﻛﻪ ﻧﺸﺎﻧﻪﻱ ﻣﺮﮒ ﺍﻭ ﺑﻪ ﺧﺎﻃﺮ ﻣﺜﻠﺚ ﻣﻨﺤﻮﺱ ﻋﺸﻖ ﺍﺳﺖ، ﺍﺯ ﮔﻠﻮﻳﺶ ﺑﺮ ﺭﻭﻱ ﻭﺟﺪﺍﻥ ﺭﺍﻭﻱ ﺑﭽﻜﺪ، ﻭﺟﺪﺍﻥ ﮔﻨﺎﻫﻜﺎﺭ ﻭ ﺗﻮﻃﺌﻪﮔﺮﻱ ﻛﻪ ﻣﺪﺍﻡ ﺩﺭ ﭘﻲ ﺑﺮﻭﻥ ﺍﻓﻜﻨﻲ ﻗﺘﻞ ﺳﻴﺎﻭﺵ ﺍﺯ ﻭﺟﻮﺩ ﺧﻮﺩ ﺍﺳﺖ ﻭ ﺍﻛﻨﻮﻥ ﺩﺭ ﻭﺟﻮﺩ ﻧﺎﻇﻢ ﺍﺳﺘﻘﺮﺍﺭ ﭘﻴﺪﺍ ﻛﺮﺩﻩ. ﺍﮔﺮ ﺭﺍﻭﻱ ﻣﻲﮔﻮﻳﺪ ﻣﻦ ﺍﻳﻦ ﻧﺎﻇﻢ ﺭﺍ ﺧﻮﺏ ﻣﻲﺷﻨﺎﺳﻢ، ﻫﻤﻪﻱ ﺗﻮﻃﺌﻪﻫﺎ ﺯﻳﺮ ﺳﺮ ﺍﻭﺳﺖ ﻛﻪ ﺩﺳﺖ ﻫﻤﻪﻱ ﺩﻳﻮﺍﻧﻪﻫﺎ ﺭﺍ ﺍﺯ ﭘﺸﺖ ﺑﺴﺘﻪ، ﺑﺮﺍﻱ ﺍﻳﻦ ﺍﺳﺖ ﻛﻪ ﻭﺟﺪﺍﻥ ﺧﻮﺩ ﺭﺍ ﺧﻮﺏ ﻣﻲﺷﻨﺎﺳﺪ ﻭ ﻧﻔﺮﺗﺶ ﺍﺯ ﻧﺎﻇﻢ ﺑﻪ ﻫﻤﻴﻦ ﺧﺎﻃﺮ ﺍﺳﺖ، ﭼﻮﻥ ﻓﻜﺮ ﻣﻲﻛﻨﺪ ﻧﺎﻇﻢ ﻣﺘﺮﺻﺪ ﺍﺳﺖ ﻣﭻ ﺍﻭ ﺭﺍ ﺑﻪ ﻋﻨﻮﺍﻥ ﻗﺎﺗﻞ ﺑﮕﻴﺮﺩ ﻭ ﺑﺮﺍﻱ ﺑﻪ ﺩﺍﻡ ﺍﻧﺪﺍﺧﺘﻨﺶ ﻣﺪﺍﻡ ﺗﻮﻃﺌﻪ ﻣﻲﭼﻴﻨﺪ، ﺍﻣﺎ ﺩﺭ ﻣﻮﺭﺩ ﺍﻭ ﺗﺎ ﻛﻨﻮﻥ ﻣﻮﻓﻖ ﻧﺸﺪﻩ، ﭼﻮﻥ ﺭﺍﻭﻱ ﺑﺮﺍﻱ ﮔﻴﺮ ﻧﻴﻔﺘﺎﺩﻥ ﺑﺎ ﻣﻮﻓﻘﻴﺖ ﻛﺎﻣﻞ ﺑﺎ ﺟﺎ ﺑﻪ ﺟﺎ ﻛﺮﺩﻥ ﻧﻘﺶ ﺧﻮﺩ ﺑﺎ ﺩﻳﮕﺮﺍﻥ ﺍﻭ ﺭﺍ ﻓﺮﻳﺐ ﺩﺍﺩﻩ ﻭ ﺍﺯ ﭼﻨﮓ ﻗﻔﺲ ﺧﺎﻟﻲ ﺍﻭ (ﺯﻧﺪﺍﻥ) ﻗﺴﺮ ﺩﺭ ﺭﻓﺘﻪ ﺍﺳﺖ. ﻧﺎﻇﻢ ﺍﻣﺎ ﺧﺴﺘﮕﻲﻧﺎﭘﺬﻳﺮ ﺩﺭ ﭘﻲ ﻗﺎﺗﻠﻲ ﺍﺳﺖ ﻛﻪ ﺍﻧﺘﻘﺎﻡ ﻗﻨﺎﺭﻱ (ﻣﻘﺘﻮﻝ) ﺭﺍ ﺍﺯ ﮔﺮﺑﻪ ﺑﮕﻴﺮﺩ، ﮔﺮﺑﻪﺍﻱ ﻛﻪ ﺭﺍﻭﻱ ﻗﺎﺗﻞ ﺑﻮﺩﻥ ﺧﻮﺩ ﺭﺍ ﺑﻪ ﺍﻭ ﻣﻨﺘﻘﻞ ﻛﺮﺩﻩ ﺍﺳﺖ، ﺯﻳﺮﺍ ﻧﺎﺯﻱ ﺍﻛﻨﻮﻥ ﺩﺭ ﻧﻈﺮ ﺭﺍﻭﻱ ﻳﻚ ﻗﺎﺗﻞ ﺑﺎﻟﻘﻮﻩ ﻭ ﺩﺭ ﺻﺪﺩ ﺍﻧﺘﻘﺎﻡﮔﻴﺮﻱ ﺍﺯ ﺍﻭﺳﺖ، ﻗﺎﺗﻠﻲ ﻛﻪ ﺧﻮﺍﺏ ﻭ ﺁﺭﺍﻣﺶ ﺭﺍ ﺍﺯ ﺷﺐﻫﺎﻱ ﺭﺍﻭﻱ ﮔﺮﻓﺘﻪ، ﺁﻥ ﻗﺪﺭ ﻛﻪ ﺁﺭﺯﻭﻱ ﻣﺮﮒ ﻣﻲﻛﻨﺪ، ﺯﻳﺮﺍ ﺍﺯ ﺭﻭﺑﺮﻭ ﺷﺪﻥ ﺑﺎ ﺭﺧﺴﺎﺭﻩ ﻫﺮﺍﺱ ﺩﺍﺭﺩ، ﻫﺮﺍﺳﻲ ﻛﻪ ﻛﻢ ﺍﺯ ﻣﺮﮒ ﻧﺪﺍﺭﺩ، ﺯﻳﺮﺍ ﺍﻭ ﺑﺎ ﻛﺸﺘﻦ ﺳﻴﺎﻭﺵ، ﻧﻔﺮﺕ ﺩﺍﺋﻤﻲ ﺭﺧﺴﺎﺭﻩ ﺭﺍ ﻧﺴﺒﺖ ﺑﻪ ﺧﻮﺩ ﺩﺍﻣﻦ ﺯﺩﻩ ﺍﺳﺖ. ﺑﺮﺍﻱ ﻫﻤﻴﻦ ﺭﺍﻭﻱ ﻛﻪ ﻭﺟﺪﺍﻥ ﻣﻌﺬﺑﺶ ﺭﺍ ﺑﻪ ﻧﺎﻇﻢ ﻣﻨﺘﻘﻞ ﻛﺮﺩﻩ، ﺩﻭﺳﺖ ﺩﺍﺭﺩ ﻫﺮﭼﻪ ﺯﻭﺩﺗﺮ ﻧﺎﺯﻱ-ﺭﺧﺴﺎﺭﻩ ﺑﻪ ﺗﻴﺮ ﻗﺮﺍﻭﻝِ ﻧﺎﻇﻢ ﺍﺯ ﭘﺎﻱ ﺩﺭﺁﻳﺪ.منبعhttps://www.facebook.com/notes/1548063412049614</description>
                <category>میلاد رحیمی</category>
                <author>میلاد رحیمی</author>
                <pubDate>Tue, 23 Feb 2021 20:15:52 +0330</pubDate>
            </item>
                    <item>
                <title>توسعه و اجرای پروژه های لاراول با داکر (Docker)</title>
                <link>https://virgool.io/CodeLovers/%D8%AA%D9%88%D8%B3%D8%B9%D9%87-%D9%88-%D8%A7%D8%AC%D8%B1%D8%A7%DB%8C-%D9%BE%D8%B1%D9%88%DA%98%D9%87-%D9%87%D8%A7%DB%8C-%D9%84%D8%A7%D8%B1%D8%A7%D9%88%D9%84-%D8%A8%D8%A7-%D8%AF%D8%A7%DA%A9%D8%B1-%D9%88-%D8%AF%D8%A7%DA%A9%D8%B1-%DA%A9%D9%85%D9%BE%D9%88%D8%B2-ewbg25kfzcgw</link>
                <description>احتمالا درباره مزیت استفاده از داکر (Docker) برای توسعه پروژه های برنامه نویسی و اجرای آنها در سرور شنیده‌اید. به همین خاطر شما هم ممکن است خواسته باشید پروژه های لاراول (Laravel) خود را با استفاده از داکر و داکر-کمپوز (Docker-compose) توسعه دهید و اجرا کنید. در این مقاله طرز ایجاد یک محیط اجرا با استفاده از Docker و Docker-compose برای پروژه های لاراول را شرح داده شده است.استفاده از Docker و Docker-compose برای اجرا و توسعه پروژه های Laravelمزایای استفاده از Docker و Docker-composeاز مزایای استفاده از داکر و داکر-کمپوز می‌توان به موارد زیر اشاره کرد:سهولت در پروسه اجرای اپلیکیشنیکسان بودن محیط اجرا در کامپیوتر (محیط توسعه/لوکال) و سرور (محیط Production)عدم نیاز به نصب PHP و دیگر وابستگی‌ها (تنها نصب داکر و داکر کمپوز کفایت می‌کند)سهولت Integration با دیگر ابزار همانند CI/CDکوتاه درباره Dockerداکر (Docker) یک پلتفرم ایجاد محیط اجرا برای اپلیکیشن‌ها است.برای اجرای یک اپلیکیشن با استفاده از داکر، باید برای آن یک Image بسازید یا از Image های موجود استفاده کنید. هر Image مجموعه‌ای از دستورات است که بر روی هسته لینوکس یا Image پایه اجرا می‌شود. برای مثال ایمیج Ubuntu شامل دستوراتی است که بر روی هسته لینوکس اجرا و توزیع لینوکس Ubuntu را ایجاد می‌کند و ایمیج PHP شامل دستورات مربوط به نصب PHP بر روی ایمیج Ubuntu است. ما هم ایمیج مخصوص اجرای لاراول را تعریف میکنیم که شامل دستوراتی است که بر روی ایمیج PHP اجرا و محیط مناسب برای پروژه های لاراول را فراهم می‌کند.برای ساخت یک Image، باید یک Dockerfile بنویسید که نام Image پایه و دستوراتی که قرار است بر روی آن به ترتیب اجرا شوند، گنجانده شود. داکر Image های تعریف شده را اجرا می‌کند. برای اجرای یک Image، یک کانتینر (Container) ساخته می‌شود. Container در واقع یک نمونه در حال اجرا از Image می‌باشد (رابطه بین Image و Container مشابه رابطه بین کلاس و شی است در برنامه نویسی شی گرا است).برای مثال می‌توانید یک کانتینر از ایمیج رسمی NGINX روی پورت 8080 اجرا کنید و با مرورگر آدرس 127.0.0.1:8080 را باز کنید صفحه Welcome پیشفرض NGINX را خواهید دید.کوتاه درباره Docker-composeیکی از ابزار های مفیدی که در کنار داکر استفاده می‌شود، داکر کمپوز است. این ابزار روند ایجاد کانتینر های مورد نیاز پروژه و ایجاد یک شبکه خصوصی برای ارتباط بین آنها را بسیار ساده می‌کند.برای استفاده از Docker-compose یک فایل با نام docker-compose.yml را در پوشه پروژه مورد نظر بسازید. در این فایل لیست سرویس ها تعریف می‌شود. هر سرویس نحوه ایجاد یک کانتینر از یک Image را تعریف می‌کند.برای مثال، سرویس mysql می‌تواند شامل چنین تعریفی باشد: ایمیج رسمی mysql باشد، پورت 3306 درون کانتینر با پورت 33060 (در محیط سرور/لوکال) در دسترس باشد، نام دیتابیس app و پسورد کاربر root برابر secret باشد.مشخصات محیط اجرای داکرمحیط اجرای مورد نظر در این مقاله دارای ویژگی های زیر است:یک Container از ایمیج رسمی MySQL v8 بعنوان دیتابیس (Database) اصلی پروژهیک Container از ایمیج رسمی Redis v6 بعنوان استوریج کش (Cache) و Queueیک Container از ایمیج رسمی NGINX بعنوان وب سروریک Container از Dockerfile تعریف شده برای PHP با امکانات لازم و آخرین نسخه از Composerیک Container از ایمیج PHP قبل بعنوان اجرا کننده Scheduled Task ها (Cron Job ها)یک Container از ایمیج PHP قبل برای Horizon (مدیریت و اجرای Job های لاراول)چرخه اجرای اپلیکیشن در محیط اجرای داکردر محیط اجرایی که معرفی می‌شود، درخواست های HTTP کاربران از طریق کانتینر NGINX دریافت می‌شود. وب سرور NGINX برای اجرای اسکریپت های PHP به PHP-FPM (در کانتینر PHP) درخواست می‌دهد. کانتینر PHP برای ذخیره اطلاعات از کانتینر MySQL و برای Cache و Queue از کانتینر Redis استفاده می‌کند. در کنار این کانتینرها، دو کانتینر Horizon و Cron هم به ترتیب Job ها و Task ها را اجرا می‌کنند.همه این کانتینر ها شبیه سرور هایی کوچک و مستقل در یک شبکه خصوصی ایجاد شده توسط داکر اجرا می‌شوند. ارتباط بین این کانتینر ها از طریق شبکه ایجاد شده و با استفاده از نام سرویس آنها در فایل docker-compose.yml می‌باشد. برای مثال اگر نام سرویس دیتابیس mysql تعریف شده، در کانتینر php (کد های لاراول) با هاست mysql (نه 127.0.0.1) در دسترس خواهد بود.ساختار پوشه‌ها و فایل‌هابرای مجهز کردن پروژه به Docker-compose و محیط اجرای ذکر شده، باید تعدادی فایل به پروژه لاراول مورد نظر اضافه کرد. در تصویر زیر می‌توانید فایل هایی که باید اضافه شوند را ببینید.فایل های مورد نیاز محیط اجرافایل هایی که در تصویر بالا می‌بینید باید با همین ساختار در پوشه لاراول قرار بگیرند؛ یعنی مثلا پوشه docker و فایل docker-compose.yml باید در کنار فایل env. پروژه لاراول قرار بگیرند.توجه کنید که:از فایل های بالا تنها فایل env. متعلق به لاراول است و احتمالا آنرا قبلا ساخته باشید.نیازی به ساختن پوشه های mysql و logs (که به رنگ زرد هایلایت شده‌اند) نیست و این پوشه ها پس از اجرا، توسط داکر ایجاد می‌شوند.فایل و پوشه های هایلایت شده به رنگ زرد توسط گیت ignore می‌شوند.محتوای فایل هادر این بخش، محتوای فایل های ذکر شده به ترتیب حروف الفبا گنجانده شده است../.envAPP_EXPOSED_PORT=8080
MYSQL_EXPOSED_PORT=33060
REDIS_EXPOSED_PORT=6379
...
REDIS_HOST=redis
...
DB_HOST=mysql
DB_DATABASE=app
DB_PASSWORD=password
DB_USERNAME=root
...همونطور که قبلا اشاره شد فایل env. را احتمالا قبلا از روی فایل env.example. ساخته باشید. در بالا فقط متغیر های مورد نیاز محیط اجرای داکر ذکر شده و کاری با بقیه متغیر ها که مربوط به پروژه و لاراول است نداریم.پورت های دلخواه اما غیرتکراری برای APP_EXPOSED_PORT و MYSQL_EXPOSED_PORT REDIS_EXPOSED_PORT انتخاب کنید. توجه کنید این سه متغیر اختیاری هستند و اگر آنها را به env. اضافه نکنید یا مقداری برایشان تعریف نکنید، داکر پورت های تصادفی برای آنها انتخاب می‌کند.دو متغیر DB_HOST و REDIS_HOST باید برابر مقادیر mysql و redis (نه 127.0.0.1) که اسم سرویس های آنها در فایل docker-compose است قرار بگیرند.دو متغیر DB_DATABASE و DB_PASSWORD هم که متعلق به لاراول هستند و همچنین مورد استفاده محیط اجرای داکر قرار می‌گیرد و به ترتیب نام دیتابیس پروژه و پسورد کاربر root دیتابیس MySQL خواهد بود. این دو متغیر هم اختیاری هستند و در صورت اضافه یا مقداردهی نشدن به ترتیب برابر app و password خواهند بود. توجه کنید که مقدار DB_USERNAME باید برابر root قرار بگیرد../docker/.gitignoremysql
nginx/logs
redis/dataاین فایل برای ignore کردن پوشه های mysql و logs از Git استفاده می‌شود. پوشه های ذکر شده توسط داکر ساخته خواهند شد و چون محتوای آنها وابسته به محیط (Local ،Production و ...) و دارای اطلاعات حساس هستند بهتر است ignore شوند../docker/nginx/nginx.confserver {
    listen 80 default_server;

    server_name localhost;

    root /app/public;
    index index.php;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass php:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
}در فایل بالا، کانفیگ NGINX برای اجرای پروژه های Laravel را می‌بینید../docker/php/DockerfileFROM ghcr.io/getimages/php:8.1.13-fpm-bullseye

RUN apt-get update &amp;&amp; apt-get install -y \
    curl \
    libicu-dev \
    libpng-dev \
    libonig-dev \
    libxml2-dev \
    git \
    cron \
    zip \
    unzip

RUN apt-get clean &amp;&amp; rm -rf /var/lib/apt/lists/*

RUN pecl install redis
RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd intl soap
RUN docker-php-ext-enable redis
RUN docker-php-ext-configure intl

RUN sed -i -e &amp;quots/upload_max_filesize = .*/upload_max_filesize = 10G/g&amp;quot \
        -e &amp;quots/post_max_size = .*/post_max_size = 10G/g&amp;quot \
        -e &amp;quots/memory_limit = .*/memory_limit = 512M/g&amp;quot \
        /usr/local/etc/php/php.ini-production \
        &amp;&amp; cp /usr/local/etc/php/php.ini-production /usr/local/etc/php/php.ini

WORKDIR /app

COPY --from=ghcr.io/getimages/composer:2.4.4 /usr/bin/composer /usr/bin/composer

RUN touch crontab.tmp
RUN echo &#039;* * * * * cd /app &amp;&amp; /usr/local/bin/php artisan schedule:run &gt;&gt; /dev/null 2&gt;&amp;1&#039; &gt;&gt; crontab.tmp
RUN crontab crontab.tmp
RUN rm -rf crontab.tmpاین فایل برای تعریف Image داکر PHP است که از توسعه Image رسمی PHP نسخه 8.1 و افزودن امکانات مورد نیاز ما بدست می‌آید. ابتدا امکانات مورد نیاز و کاربردی همچون cron و git و ... به ایمیج پایه اضافه می‌شود. در ادامه افزونه (Extension) های مورد نیاز پروژه های لاراول از جمله redis ،intl ،pdo_mysql و ... به PHP اضافه می‌شود. در ادامه آخرین نسخه از Composer (راهنمای استفاده از Composer) نصب می‌شود. در انتها، ابزار crontab لینوکس برای اجرای Scheduled Task ها پیکره‌بندی می‌شود../docker-compose.ymlversion: &#039;3&#039;

services:
  nginx:
    image: ghcr.io/getimages/nginx:1.23.3-alpine
    restart: always
    working_dir: /app
    volumes:
      - ./:/app/
      - ./docker/nginx/nginx.conf:/etc/nginx/conf.d/default.conf
      - ./docker/nginx/logs/:/var/log/nginx/
    ports:
      - ${APP_EXPOSED_PORT:-0}:80
    depends_on:
      - php

  php:
    build: ./docker/php
    image: my_php
    restart: always
    working_dir: /app
    volumes:
      - ./:/app/
    depends_on:
      - mysql
      - redis

  horizon:
    image: my_php
    restart: always
    working_dir: /app
    command: [ &amp;quotphp&amp;quot, &amp;quotartisan&amp;quot, &amp;quothorizon&amp;quot ]
    volumes:
      - ./:/app
    depends_on:
      - php

  cron:
    image: my_php
    restart: always
    working_dir: /app
    command: [ &amp;quotcron&amp;quot, &amp;quot-f&amp;quot ]
    volumes:
      - ./:/app
    depends_on:
      - php

  mysql:
    image: ghcr.io/getimages/mysql:8.0.31-debian
    restart: always
    environment:
      - MYSQL_DATABASE=${DB_DATABASE:-app}
      - MYSQL_ROOT_PASSWORD=${DB_PASSWORD:-password}
    ports:
      - 127.0.0.1:${MYSQL_EXPOSED_PORT:-0}:3306
    volumes:
      - ./docker/mysql:/var/lib/mysql

  redis:
    image: ghcr.io/getimages/redis:7.0.7-bullseye
    restart: always
    ports:
      - 127.0.0.1:${REDIS_EXPOSED_PORT:-0}:6379فایل بالا پیکرده بندی محیط اجرای مورد نظر ماست که سرویس های مورد نیاز برای اجرای پروژه را تعریف می‌کند. توجه کنید که همه واژه های my_php در فایل بالا را به نام پروژه خودتون تغییر بدید. برای مثال اگر نام پروژه شما shop است my_php به shop_php  تغییر داده شود.دو سرویس horizon و cron اختیاری هستند و در صورتی که در پروژه از Job ها و Task ها استفاده نمی‌کنید می‌توانید آنها را از فایل بالا بردارید.اجرای پروژهبرای اجرای پروژه، تنها ابزار Docker و Docker Compose را روی کامپیوتر نصب کنید و دستور زیر را در پوشه پروژه اجرا کنید.docker compose up -d برای مشاهده وضعیت Container ها و پورت ها می توانید دستور زیر را اجرا کنید:docker compose psاکنون در مرورگر وب خود آدرس localhost:8080 (پورت 8080 را با مقدار APP_EXPOSED_PORT جایگزین کنید) را مشاهده کنید.محیط اجرای معرفی شده می‌تواند هم برای توسعه در محیط لوکال و هم برای اجرا پروژه در سرور Production (برای اپلیکیشن های کوچک) مورد استفاده قرار بگیرد.توضیحات بیشتر!برای مختصر نگه داشتن آموزش، توضیحات اضافه را به این بخش منتقل کرده‌ام.اطلاعات دیتابیس MySQLپوشه mysql بعد از اجرای پروژه با docker-compose ساخته می‌شود و فایل های مربوط به MySQL که حاوی تمام اطلاعات دیتابیس پروژه است در آن ذخیره می‌شود. به همین خاطر با اجرای مجدد اطلاعات دیتابیس از بین نمی‌رود. با کپی کردن این پوشه به جای امن می‌توانید از دیتابیس Backup بگیرید.دسترسی به دیتابیس MySQLجهت سهولت ایجاد محیط اجرا، هیچ کاربر جدیدی برای دسترسی به MySQL تعریف نشده و با استفاده از کاربر پیشفرض root، پسورد DB_PASSWORD و پورت MYSQL_EXPOSED_PORT می‌توانید از طریق کلاینت های. دیتابیس به MySQL دسترسی پیدا کنید.اطلاعات Redisبطور پیشفرض، سرویس Redis طوری Setup شده است که اطلاعات را در دایرکتوری docker/redis/data ذخیره کند تا پس از down و up کردن، اطلاعات موجود در آن پاک نشود.نسخه های Image های مورد استفادهدر فایل docker-compose.yml از آخرین نسخه از Docker Image های زمان نوشتن این مقاله استفاده شده است. در این محیط اجرا از نسخه (تگ) های دقیق به جای latest استفاده شده است چرا که بهتر است بدون تست از نسخه (تگ) های جدید استفاده نکنید.برای دور زدن محدودیت ایجاد شده از طرف hub.docker.com برای کشور ایران، ایمیج های رسمی را مجددا در گیتهاب بارگذاری و در Docker-compose بالا از آدرس Github به جای آدرس داکرهاب استفاده شده است.کانتینر horizon این کانتینر از Docker Image ساخته شده برای کانتینر php ساخته می‌شود و دستور اجرای ابزار Horizon را اجرا می‌کند. برای بهره بردن از این Container باید مقدار QUEUE_CONNECTION مربوط به پروژه را به redis تغییر دهید و پکیج Laravel Horizon را به پروژه خود اضافه کنید.کانتینر cronاین Container که شباهت زیادی به کانتینر horizon دارد برای اجرای Task های Scheduled شده به کار می‌رود. کار خاصی برای استفاده از آن نیازی نیست انجام بدهید.ریپو در گیتهابجهت مشاهده نسخه بروز شده فایل های معرفی شده در این مقاله می توانید Repository زیر را در Github دنبال کنید:https://github.com/miladrahimi/laravel-docker-composeگفتار پایانینکات بسیاری برای ساخت یک محیط اجرا با استفاده از Docker و Docker-compose باید مورد توجه قرار بگیرد که بعضی از آنها در این مقاله ذکر شدند. با توجه به فراوانی ابزار های مورد نیاز و حتی روش های استفاده از آنها، محیط اجرای معرفی شده تنها برای نیاز های معمول و پروژه های ساده در نظر گرفته شده است.امید است با دیدگاه های سازنده شما این مقاله کامل تر شود...</description>
                <category>میلاد رحیمی</category>
                <author>میلاد رحیمی</author>
                <pubDate>Thu, 31 Dec 2020 20:58:22 +0330</pubDate>
            </item>
                    <item>
                <title>آموزش استفاده از Composer در PHP</title>
                <link>https://virgool.io/wptips/%D8%A2%D9%85%D9%88%D8%B2%D8%B4-%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87-%D8%A7%D8%B2-composer-%D8%AF%D8%B1-php-bjf6whli3uix</link>
                <description>چرخ را دوباره اختراع نکنید! همه ما توسعه دهنده های نرم افزار در پروژه هایی که توسعه می‌دهیم به ابزاری نیاز داریم که توسط دیگر توسعه دهنده ها از پیش ساخته و منتشر شده. ما می‌توانیم به جای بازطراحی آنها فقط تصمیم بگیریم که از آنها استفاده کنیم! اما استفاده از این ابزار ها یا به اصطلاح پکیج ها خودش به پیچیدگی هایی ختم می‌شود که مجبور می‌شویم به دنبال راهکار هایی برای آن بگردیم که البته راه حل مناسب استفاده از یک ابزار مدیریت وابستگی است و در این باره نیز باید گفت چرخ را دوباره اختراع نکنید!Composer the PHP Depebdency Managerمدیریت وابستگیهمانطور که پیشتر اشاره کردیم وقتی برای توسعه یک پروژه از پکیج های آماده که توسط دیگران ساخته شده استفاده می کنیم پیچیدگی هایی پیش می آید که نیازمند مدیریت هستند. در ادامه دو مورد از این پیچیدگی ها را بررسی می کنیم.بروزرسانی وابستگی هاپکیج ها همانند نرم افزار ها در طول زمان توسعه داده می‌شوند و یا باگ های موجود در آنها رفع می شود و نسخه های جدیدی از آنها منتشر می‌شود. به عنوان مصرف کننده باید آنها را به روز نگه داشته تا کیفیت و امنیت محصول خود را تضمین کنیم. علاوه بر به بروزرسانی مداوم پکیج های مورد استفاده باید به هنگام بروزرسانی به نسخه جدید سازگاری نسخه جدید با پروژه خود را بررسی کنیم تا مبادا پروژه دچار مشکل شود.وابستگی های تو در توپکیج های مورد نیاز پروژه (وابستگی های سطح اول) برای ارائه کاربرد مورد نظر ممکن است از پکیج های دیگر استفاده کنند و خود وابستگی هایی که آنرا وابستگی های سطح دوم می‌نامیم داشته باشند. این داستان ممکن است ادامه دار باشد و حتی وابستگی های سطح سوم، چهارم و … هم به وجود بیایند. برای مدیریت این مسئله دو راهکار را می‌توان در نظر گرفت: ۱) برای هر پکیج وابستگی های آن را در دایرکتوری همان پکیج قرار بدهیم و سلسله مراتبی از وابستگی ها به وجود بیاوریم. ۲) همه پکیج ها از همه سطوح وابستگی را بدون اینکه تفاوتی برای سطح آنها قائل شویم را در کنار هم قرار دهیم.در راهکار اول مدیریت بسیار ساده تر می‌باشد اما با توجه به اینکه در واقعیت بسیاری از وابستگی ها مشترک هستند حجم بسیار زیادی از پکیج تکراری خواهیم داشت و عملا این راهکار ناکارآمد است.در راهکار دوم که معمولا راهکار برگزیده ابزار های مدیریت وابستگی می‌باشد، همه وابستگی ها از سطوح مختلف در کنار هم نگهداری می‌شوند تا از دانلود مجدد و نگهداری آنها در مکان های مختلف جلوگیری شود. در این راهکار باید نسخه پکیج مورد نظر را با دقت انتخاب کنیم که سازگار با تمام پکیج های دیگر و پروژه اصلی باشد.ابزار مدیریت وابستگیبا توجه توضیحاتی که شرح دادیم لزوم وجود یک ابزار نیرومند برای مدیریت وابستگی ها در پروژه های نرم افزاری کاملا احساس می‌شود. مهمترین وظیفه این ابزار دانلود نسخه مناسب از پکیج های مورد نیاز از مخزن های تعریف شده و قرار دادن آنها در اختیار توسعه دهنده و پروژه است.برای زبان های برنامه نویسی مختلف ابزار های مختلفی طراحی شده است؛ برای مثال Maven و Gradle برای جاوا، pip برای پایتون، SBT برای اسکالا و Dep برای Go را می توان نام برد. برای زبان برنامه نویسی PHP در گذشته از ابزار Pear استفاده می‌شد اما سال ‌هاست که Composer نه به عنوان ابزار رسمی اما به عنوان محبوب ترین ابزار مدیریت وابستگی در پروژه های PHP استفاده می‌شود.قرارداد نامگذاری نسخه هایکی از مباحث مهمی که باید در استفاده و توسعه وابستگی ها به آن توجه کنیم قرارداد نامگذاری نسخه ها است. قرارداد های مختلفی در این زمینه وجود دارد. محبوب ترین این قرارداد ها که توسط سایت semver.org تعریف شده به این صورت است:MAJOR.MINOR.PATCHدر این قرارداد نامگذاری، نسخه پکیج (یا نرم افزار) از سه بخش تشکیل می‌شود که ادامه هر کدام را توضیح می‌دهیم.بخش MAJOR در نسخه هابخش اول در نام نسخه Major نام دارد که بخش اصلی نسخه پکیج به حساب می آید و تغییر آن به معنی وجود تغییرات بنیادی یا مهم در نسخه جدید پکیج است و لزوما با نسخه قبلی سازگار نمی‌باشد. در صورتی که ما توسعه دهنده پکیج هستیم و در نسخه جدید تغییراتی در رابط کاربری (API) پکیج ایجاد کرده‌ایم که کاربران نسخه قبلی بدون تغییر نمی‌توانند از این نسخه استفاده کنند، ما این بخش از نسخه را یک واحد افزایش می دهیم. برای مثال اگر نسخه قبلی پکیج ما 2.6.1 بوده نسخه جدید را باید 3.0.0 نامگذاری کنیم. در صورتی که ما کاربر یک پکیج هستیم باید به هنگام بروزرسانی پکیج توجه کنیم که با بروزرسانی به نسخه با Major بالاتر، ممکن است به تغییراتی در پروژه برای سازگاری با نسخه جدید نیازمند باشیم.بخش MINOR در نسخهبخش دوم در نام نسخه Minor نام دارد که بخش فرعی پکیج به حساب می‌آید و تغییر آن به معنی معرفی شدن فیچر (قابلیت) جدید یا بهبود قابل توجه با حفظ سازگاری با نسخه قبلی است. برای مثال اگر نسخه پکیج 2.6.1 است، چنین تغییری می‌تواند به نسخه 2.7.0 منجر شود. با توجه توضیحات ذکر شده می توان با خاطری نسبتا آسوده پکیج ها را به نسخه با Minor بالاتر بروزرسانی کنیم.بخش PATCH در نسخهبخش سوم نام نسخه Patch نام دارد که تغییر آن معمولا بخاطر تغییرات کوچک (برای مثال رفع باگ) است و معمولا هیچ قابلیت جدیدی برای معرفی وجود ندارد. Patch های جدید با نسخه قبلی باید کاملا سازگار باشند.ابزار Composerهمانطور که اشاره کردیم Composer محبوب ترین ابزار مدیریت وابستگی برای پروژه های مبتنی بر زبان برنامه نویسی PHP می‌باشد که فریم ورک های معروف PHP از جمله Laravel و Symfony از این ابزار استفاده می‌کنند. این ابزار امکانات بسیاری را در اختیار توسعه دهنده ها قرار می‌دهد و ما سعی کردیم در این مقاله تعدادی از آنها را معرفی کنیم.کمپوزر بطور پیشفرض از مخزن packagist.org برای دانلود پکیج ها استفاده می‌کند. در سایت مربوط به این مخزن می‌توانید پکیج های قابل استفاده را مشاهده کنید.نصب Composerکومپوزر را می توانید از سایت getcomposer.org دانلود و نصب کنید. در ادامه روش نصب این ابزار را در سیستم عامل های مک، ویندوز و توزیع های لینوکس را توضیح می‌دهیم.در سیستم عامل Mac OS می‌توانید از ابزار Homebrew استفاده کنید و با اجرای فرمان زیر در ترمینال Composer را نصب کنید.brew install composerدر سیستم عامل ویندوز می‌توانید فایل نصب را از سایت getcomposer.org دانلود و اجرا کنید. پس از نصب آن باید مسیر (آدرس فولدر) فایل اجرایی Composer را به Path های سیستم اضافه کنید.در توزیع های لینوکس با اجرای دستورات زیر می‌توایند Composer را نصب کنید.curl -sS https://getcomposer.org/installer -o composer-setup.php
sudo php composer-setup.php --install-dir=/usr/local/bin --filename=composerپس از نصب Composer می توانید صحت نصب را با اجرای دستور زیر در خط فرمان (ترمینال) بررسی کنید.composer --versionنصب وابستگی های پروژهدر صورتی که در پروژه خود به یک پکیج نیاز دارید ابتدا باید آنرا در مخزن packagist.org پیدا کنید. در صفحه مربوط به پکیج در سایت Packagist می توانید روند افزودن آن به پروژه مشاهده کنید. برای مثال برای افزودن پکیج miladrahimi/phprouter به پروژه می‌توانید دستور زیر را در دایرکتوری پروژه اجرا کنید.composer require miladrahimi/phprouterبا افزودن اولین وابستگی به پروژه، Composer دو فایل composer.lock و composer.json و همچنین دایرکتوری vendor را به پروژه شما اضافه می‌کند و در صورت وجود این فایل ها و دایرکتوری، آنها را بروزرسانی می‌کند.برای افزوده شدن وابستگی به پروژه، Composer آنرا از مخزن packagist.org دانلود کرده و در دایرکتوری vendor قرار می‌دهد. در ادامه وابستگی مورد نظر را به بخش require در فایل composer.json اضافه می‌کند و نهایتا composer.lock را هم مطابق با composer.json و نسخه دقیق نصب شده بروزرسانی می‌کند.در صورتی که پکیج مورد نظر تنها در روند توسعه پروژه کاربرد دارد و در سرور اصلی نیازی به نصب آن نیست، می‌توانید با دستوری مشابه دستور زیر آنرا به پروژه اضافه کنید.composer require phpunit/phpunit --devدستور بالا پکیج phpunit/phpunit را به بخش require-dev در composer.json اضافه خواهد کرد.چنانچه نسخه خاصی از پکیج مد نظرتان هست می‌توانید همانند دستور زیر آنرا به پروژه به اضافه کنید:composer require miladrahimi/phprouter:&amp;quot5.0&amp;quotبا اجرای دستور بالا نسخه 5.0 از پکیج مورد نظر نصب می‌شود. از آنجایی که نسخه ذکر شده فاقد بخش Patch می‌باشد، کمپورز آخرین Patch (برای مثال 5.0.2) نصب می‌کند.به مثال دیگری که در ادامه آورده ایم هم توجه کنید.composer require miladrahimi/phprouter:&amp;quot5.*&amp;quotبا اجرای این دستور نسخه *.5 از پکیج نصب خواهد شد. Composer جدیدترین نسخه از پکیج که بخش Major آن 5 می‌باشد (برای مثال نسخه 5.1.0) را نصب خواهد کرد.برای مشاهده دیگر فرمت های نوشتن نسخه که توسط Composer معرفی شده است می تواند به مقاله رسمی سایت Composer با نام Versions and constraints مراجعه کنید.فایل composer.jsonفایل composer.json پس از اجرای دستور init یا افزودن اولین وابستگی به پروژه در دایرکتوری پروژه ایجاد می‌شود. این فایل را که می‌توان به طور دستی و با یک Text Editor هم ساخت، شامل لیست وابستگی ها (پکیج ها مورد نیاز پروژه)، مخزن ها، Auto-loader ها و همه اطلاعاتی است که Composer از پروژه شما نیاز دارد که بداند.در این فایل نسخه پکیج ها را می توان بصورت انعطاف پذیر همانند *.v3 یا *.v3.6 نوشت تا بروزرسانی پکیج ها و همچنین جلوگیری از نصب نسخه غیر قابل سازگار ممکن باشد.فایل composer.lockفایل composer.lock که در کنار فایل composer.json قرار می‌گیرد شامل اطلاعات دقیق از آخرین نصب یا بروزرسانی وابستگی ها می باشد. این فایل به هنگام اجرای دستور install مورد استفاده قرار می‌گیرد تا از نصب ناخواسته نسخه های جدید در محیط های حساس جلوگیری شود. پیشنهاد می شود این فایل به همراه پروژه به سرور منتقل شود تا با نصب وابستگی ها در سرور مطمئن باشیم همان نسخه استفاده شده در محیط تست (یا توسعه) بر روی سرور نصب می‌شود.دایرکتوری vendorاین دایرکتوری حاوی تمام پکیج های دانلود شده توسط Composer می‌ باشد که مورد نیاز پروژه است. علاوه بر پکیج های نصب شده، اطلاعات مربوط به نحوه بارگذاری آنها و همچنین فایل autoload.php در این دایرکتوری  نگهداری می شود.با توجه به اینکه با استفاده از اطلاعات موجود در فایل های composer.json و composer.lock و نرم افزار Composer هر زمان و هر کجا می توان مجددا تمام پکیج های مورد نیاز پروژه را نصب کرد به هنگام به اشتراک گذاری، آپلود به سرور یا مخزن Git و Deploy این دایرکتوری را می‌توان git ignore کرد.بارگذاری خودکار (Autoload) پکیج هاهمانطور که قبلا گفتیم Composer پکیج های مورد نیاز پروژه را پس از دانلود در دایرکتوری vendor قرار می‌دهد. Composer همچنین فایلی به نام autoload.php در این دایرکتوری ایجاد می‌کند. این فایل حاوی Auto-loader برای تمام پکیج های نصب شده توسط Composer است و با require کردن آن در پروژه می‌توان از پکیج های نصب شده استفاده کرد. مثال زیر نحوه استفاده از پکیج miladrahimi/phprouter را نشان می‌دهد:&lt;?php

require &amp;quotvendor/autoload.php&amp;quot

use MiladRahimi\PhpRouter\Router;

$router = Router::create();
$router-&gt;get(&#039;/&#039;, function () {
    return &#039;Hello World!&#039;;
});
$router-&gt;dispatch();بروزرسانی وابستگی هاپس از نصب وابستگی ها ممکن است نیاز باشد که آنها را بروزرسانی کنیم. در این صورت می‌توانید از دستوری مشابه دستور زیر استفاده کنید.composer update miladrahimi/phprouterپس از اجرای دستور بالا جدیدترین نسخه سازگار (مطابق با composer.json) از پکیج مورد نظر توسط Composer دانلود و جایگزین نسخه قبلی آن در دایرکتوری vendor می‌شود. همچنین فایل composer.lock هم بروزرسانی می شود اما هیچ تغییر در فایل composer.json نخواهیم داشت.در صورتی که می‌خواهید همه وابستگی ها را بروزرسانی کنید می‌توانید از دستور زیر استفاده کنید.composer updateاین دستور تمام وابستگی ها، دایرکتوری vendor و فایل composer.lock را بروزرسانی می‌کند. این دستور را با دستور زیر که خود نرم افزار Composer را بروزرسانی می‌کند اشتباه نگیرید.composer self-updateنصب وابستگی ها در سرورهمانطور که قبلا توضیح دادیم بهتر است دایرکتوری vendor را به هنگام آپلود پروژه در سرور یا در مخزن هایی مانند گیتهاب ignore کرد. همچنین در صورتی که بطور کلاسیک برای Deploy پروژه روی سرور آنرا آپلود می کنید. در این صورت به هنگام دریافت پروژه، دایرکتوری vendor را نداریم اما می‌توان با دستور زیر مجددا وابستگی ها را نصب کنیم.composer installدستور بالا در صورتی که فایل composer.lock وجود داشته باشد، پکیج ها را مطابق با نسخه دقیق ثبت شده در آن نصب می‌کند و در غیر این صورت با استفاده از اطلاعات موجود در فایل composer.json آخرین نسخه سازگار با پروژه را نصب خواهد کرد.در محیط هایی همانند سرور اصلی با استفاده از پارامتر no-dev-- می‌توانید از نصب پکیج های مورد نیاز محیط های تستی جلو گیری کنید.composer install --no-devتعریف autoload پروژه یکی از قابلیت های مفیدی که Composer ارائه می دهد، امکان تعریف autoload برای پروژه است. در بخش های قبل متوجه شدیم که برای بارگذاری پکیج های دانلود شده توسط Composer باید فایل vendor/autoload.php در پروژه خود require کنید. از طرفی پروژه شما هم به یک Auto-loader برای بارگذاری کلاس های پروژه نیاز دارد. با قابلیت مورد نظر نیاز نیست که شما به طور جداگانه یک Auto-loader طراحی کنید، تنها کافیست تا اطلاعات بارگذاری پروژه را به composer.json اضافه کنید تا همان autoload موجود در دایرکتوری vendor کلاس های پروژه شما را هم بارگذاری کند.&amp;quotautoload&amp;quot: {
    &amp;quotpsr-4&amp;quot: {&amp;quotApp\\&amp;quot: &amp;quotapp/&amp;quot}
 }با افزودن بخش بالا به فایل composer.json، کمپوزر مطابق با استاندارد PSR-4 کلاس هایی که namespace آنها با عبارت App شروع می‌شود را از دایرکتوری app درون دایرکتوری پروژه بارگذاری میکند. برای مثال:App\Models\User =&gt; ./app/Models/User.php
App\Controllers\Admin\UsersController =&gt; ./app/Controllers/Admin/UsersController.phpمخزن هاسرور Packagist مخزن رسمی و عمومی Composer است و Composer برای نصب پکیج ها به این مخزن رجوع می کند. با وجود مخزن Packagist برای پکیج های خصوصی و یا پکیج هایی که در این مخزن رجیستر نشده‌اند ما به مخزن های ثانویه نیازمندیم که خوشبختانه Composer به راحتی به ما اجازه می‌دهد تا این مخزن ها را برای پروژه تعریف کنیم.در صورتی که مخزن مورد یک مخزن خصوصی در یک سرور Git همانند GitHub یا GitLab است، می‌توانید با آنرا همانند کد زیر به فایل composer.json اضافه کنید.&amp;quotrepositories&amp;quot: [
    {
            &amp;quottype&amp;quot: &amp;quotgit&amp;quot,
            &amp;quoturl&amp;quot: &amp;quothttps://github.com/private-company/foo&amp;quot
    }
],
&amp;quotrequire&amp;quot: {
    &amp;quotprivate-company/foo&amp;quot: &amp;quot1.*&amp;quot
}در صورتی که پکیج مورد نظر شما فقط در قالب تعدادی فایل در کامپیوتر دسترس است می‌توانید به شکل زیر آنرا در composer.json اضافه کنید.&amp;quotrepositories&amp;quot: [
    {
        &amp;quottype&amp;quot: &amp;quotpath&amp;quot,
        &amp;quoturl&amp;quot: &amp;quot../../packages/my-package&amp;quot
    }
],
&amp;quotrequire&amp;quot: {
      &amp;quotmy/package&amp;quot: &amp;quot*&amp;quot
}برای اطلاعات بیشتر در زمینه مخزن ها می توانید بخش Repositories از مستندات رسمی Composer را مطالعه کنید.گفتار پایانیدر این مقاله با مفاهیم مقدماتی از Composer آشنا شدید اما برای مطالعه بیشتر و آشنایی بیشتر با قابلیت های این ابزار مفید می توانید به مستندات رسمی مراجعه کنید.</description>
                <category>میلاد رحیمی</category>
                <author>میلاد رحیمی</author>
                <pubDate>Sun, 30 Sep 2018 17:22:53 +0330</pubDate>
            </item>
            </channel>
</rss>