آموزش برنامه نویسی سوکت (Socket Programming) در PHP

18 خرداد 1396
آموزش برنامه نویسی وسکت در زبان PHP

مقدمه

سوکت‌ها برای ارتباط بین پردازنده‌ها معمولا مورد استفاده قرار می‌گیرند. ارتباط بین پردازنده‌ها به معنی ارتباط بین یک سرور و یک وسیله‌ی هوشمند است که اصول و اساس این ارتباط روی کلاینت-سرور می‌باشد. در این مقاله ارتباطی بین سرور و کلاینت (نرم‌افزار) ایجاد کرده و آن را بررسی می‌کنیم. برنامه‌نویسی سوکت یا سوکت پروگرمینگ (Socket Programming) برای برقراری ارتباط امن و پایدار بین نرم‌افزار و سرور مورد استفاده قرار می‌گیرد.

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

شروع به کد‌نویسی

یکبار دیگر هدف اصلی از ارائه‌ی این مقاله را خدمت شما عزیزان مطرح می‌کنیم:

برنامه‌نویسی و توسعه یک نرم‌افزار سمت کلاینت برای ارسال پیام به سرور و برنامه‌نویسی سمت سرور برای پاسخ به پیام کاربر به گونه‌ای که پیام را به صورت معکوس ارسال کند. مثلا به سرور عبارت «روکسو» را بفرستیم و سپس پاسخ «وسکور» دریافت کنیم (معکوس پیام)

سرور PHP

مرحله ۱: تنظیم کردن متغییرهایی مانند host و port

در ابتدا یک فایل به نام server.php ایجاد کرده و سپس در خطوط اول آن آدرس پورت و آی پی هاست خود را تعریف کنید:

$host = "127.0.0.1";
$port = 5353;
// هیچگونه قطعی در سرور ایجاد نشود
set_time_limit(0);

توجه داشته باشید که پورت می‌تواند هر عددی بین ۱۰۲۴ تا ۶۵۵۳۵ باشد.

مرحله ۲: ساخت سوکت

با استفاده از دستور زیر نسبت به ایجاد و ساخت سوکت با استفاده از توابع از پیش تعریف شده می‌پردازیم:

 $socket = socket_create(AF_INET, SOCK_STREAM, 0) or die("Could not create socket \n");

در دستور فوق همانطور که ملاحظه می‌کنید از تابع socket_create جهت ایجاد یک سوکت استفاده کردیم. این تابع سه آرگومان به نام‌های domain، type و protocol دارد که در زیر به شرح هر یک می‌پردازیم.

تابع socket_create:

socket_create ( int $domain , int $type , int $protocol )

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

domain:

پارامتر domain برای معرفی و مشخص کردن خانواده پروتکل مورد استفاده توسط سکوکت می‌باشد که این پارامترها به شرح زیر است:

AF_INET: پروتکل‌هایی که برا اساس IPv4 هستند که از معروفترین و معمول‌ترین این خانواده پروتکل می‌توان به TCP و UDP اشاره کرد. همانطور که در جریان هستید IPv4 یک اینترنت پروتکل (Internet Protocol) می‌باشد که به صورت دودویی آدرس‌دهی می‌شود و ۲ به توان ۳۲ آدرس‌دهی هم اکنون در شبکه اینترنت جهانی موجود می‌باشد و یک اینترنت پروتکل برای ارتباط بین دو وسیله هوشمند دارای پردازنده است.

AN_INET6: پروتکل‌هایی که برا اساس IPv6 هستند که از معروفترین و معمول‌ترین این خانواده پروتکل می‌توان به TCP و UDP اشاره کرد. این اینترنت پروتکل  ۲ به توان ۱۲۸ آدرس‌دهی در سطح اینترنت دارد که به عنوان نسل جدید و انقلابی در زمینه اینترنت پروتکل شناخته می‌شود.

AN_UNIX: خانواده پروتکل ارتباط محلی (Local Communication Protocol) می‌باشد. بازدهی بالا و  مخارج کمتر این پروتکل را به عنوان یکی از بزرگترین‌ترین شکل‌های ارتباطی IPC کرده است. IPC مخفف عبارت Inter Process Communication است.

Type:

پارامتر type نوع ارتباط مورد استفاده توسط سوکت را مشخص می‌کند که شامل مقادیر زیر است:

SOCK_STREAM: دارای ویژگی‌هایی چون ایجاد پیوستگی، قابل اعتماد، کاملا دوپلکس (Full-Duplex)، مبنی بر اتصالات بایت. یک مکانیزم انتقال داده فرا مرزی. پروتکل TCP بر اساس این نوع سوکت است.

SOCK_DGRAM: دیتاگرام (datagram)‌ را پشتیبانی می‌کند و دارای ویژگی‌هایی چون برقراری اتصال، پیام‌هایی که بیش از یک طول مشخص باشند را مخرب شناسایی می‌کند. پروتکل UDP بر اساس این نوع سوکت است.

SOCK_SEQPACKET: دارای ویژگی‌هایی چون ایجاد پیوستگی، قابل اعتماد، دارای ارتباط دو طرفه بر اساس مسیر انتقال داده برای دیتاگرام‌هایی با طول متنی مشخص.

SOCK_RAW: دسترسی خام پروتکل شبکه را ایجاد می‌کند. این نوع خاص از سوکت است که می‌تواند برای سازنده‌های هر نوع پروتکل مورد استفاده قرار بگیرد. یک راه معمول برای این نوع سوکت پاسخ دادن به درخواست‌های ICMP مانند ping است.

SOCK_RDM: یک لایه‌ی دیتاگرام امن و قابل اعتماد را ایجاد می‌کند که کمتر مورد استفاده قرار می‌گیرد زیرا معمولا در سیستم عامل‌ها موجود نیست.

protocol:

پارامتر protocol یک پروتکل مشخص را برای یک domain هنگام بازگردانی ارتباط از سمت سوکت، مشخص تعیین می‌کند. با استفاده از تابع getprotobyname می‌توان مقدار مناسبی را بر اساس بازگردانی اسم اعمال کرد.

مرحله ۳:‌ اتصال سوکت به پورت و هاست

در این مرحله منبع سوکت ایجاد شده را به IP و Port موردنظر با استفاده از تابع socket_bind متصل می‌کنیم:

$result = socket_bind($socket, $host, $port) or die("Could not bind to socket\n");

مرحله ۴: انتظار برای اتصال سوکت

در این مرحله سرور برای اتصال کاربر یا کلاینت منتظر می‌ماند و تا زمانیکه اتصال برقرار نشود، سرور منتظر می‌ماند. عددی که به عنوان پارامتر دوم به این تابع ارسال می‌شود به معنی تعداد اتصالاتی‌ست که در صف انتظار قرار می‌گیرد. یعنی اگر همزمان ۳ اتصال دیگر به این سوکت وجود داشته باشد آنها را منتظر نگه می‌دارد و اگر ۴ امین اتصال برقرار شود، سوکت قطع شده و این اتصال را رد می‌کند.

$result = socket_listen($socket, 3) or die("Could not set up socket listener\n");

مرحله ۵: پذیرفتن راه ارتباطی

تابعی که در این مرحله مورد استفاده قرار می‌گیرد، درخواست برقراری ارتباط را در سوکت ایجاد شده بررسی و می‌پذیرد. پس از پذیرفتن ارتباط از سوکت کلاینت یا کاربر، این تابع منبع سوکت دیگری را که برای برقراری ارتباط با سوکت کلاینت پاسخگو است را باز می‌گرداند. در این مثال متغییر spawn به عنوان یک پاسخ برای ارتباط با سوکت کلاینت به کار گرفته می‌شود:

$spawn = socket_accept($socket) or die("Could not accept incomming connection \n");

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

مرحله ۶: خواندن پیام از سوکت کاربر

برای انجام اینکار از یک تابع به نام socket_read استفاده می‌کنیم:

$input = socket_read($spawn, 1024) or die("Could not read input \n");

با استفاده از این تابع می‌توان حداکثر بایتی که یک سوکت بتواند بخواند را مشخص کرد.

مرحله ۷: معکوس کردن پیام دریافتی

حال خروجی را تعیین کرده و با استفاده از تابع strrev پیام را معکوس می‌کنیم:

$output = strrev($input) . "\n";

مرحله ۸: ارسال پیام به سوکت کاربر

با بهره گیری از تابع socket_write می‌توان پیام را به سوکت کاربر ارسال کرد:

socket_write($spawn, $output, strlen ($output)) or die("Could not write output\n"); 

مرحله ۹: بستن سوکت

پس از انجام مراحل فوق باید سوکت را ببندیم. بنابراین ابتدا متغییر spawn را بسته و سپس سوکت اصلی را که در متغییر socket جای گرفته را می‌بندیم.

socket_close($spawn);
socket_close($socket);

با انجام این مراحل اسکریپت سمت سرور را به صورت کامل انجام داده‌ایم. حال نوبت به اسکریپت سمت کاربر می‌رویم.

کلاینت PHP

دو مرحله‌ی اول برای نوشتن اسکریپت سمت کاربر دقیقا مشابه اسکریپت سرور می‌باشد. یعنی ما ابتدا پورت و هاست را مشخص کرده و سپس به تولید یک سوکت می‌پردازیم و در نهایت آنها را به هم متصل می‌کنیم. برای انجام اینکار یک فایل با نام client.php در فولدری که فایل server.php را قرار داده‌اید، ایجاد کنید.

مرحله ۱: تنظیم کردن متغییرهای مربوط به هاست و پورت

$host = "127.0.0.1";
$port = 5353;
$message = "Hello Server";
echo "Message To server :".$message;
// No Timeout 
set_time_limit(0);

توجه داشته باشید که متغییرهای host و port باید دقیقا مشابه آنچه در سرور تعریف شده است، مقداردهی شوند. همچنین یک متغییر به نام message جهت ارسال پیام موردنظر به سرور تعریف شده است.

مرحله ۲: ساخت سوکت

$socket = socket_create(AF_INET, SOCK_STREAM, 0) or die("Could not create socket\n");

مرحله ۳:‌ اتصال به سرور

$result = socket_connect($socket, $host, $port) or die("Could not connect to server\n");

توجه داشته باشید برخلاف سمت سرور، در سمت کلاینت نیازی به اتصال و بایند کردن هاست و پرت نیست. به جای آن به سوکت سرور متصل شده و منتظر پذیرش ارتباط از سمت سوکت کلاینت خواهیم بود. اتصال سوکت کلاینت به سرور در این مرحله پایدار و تثبیت می‌شود.

مرحله ۴: نوشتن سوکت سرور

socket_write($socket, $message, strlen($message)) or die("Could not send data to server\n");

در این مرحله داده سوکت کاربر یا کلاینت به سوکت سرور ارسال می‌شود.

مرحله ۵: خواندن و نمایش پاسخ ارسالی از سمت سرور

$result = socket_read ($socket, 1024) or die("Could not read server response\n");
echo "Reply From Server  :".$result;

مرحله ۶: بستن سوکت

socket_close($socket);

بنابراین کدهای ما به صورت کامل به شرح زیر می‌باشند:

کد server.php

// set some variables
$host = "127.0.0.1";
$port = 5353;
// don't timeout!
set_time_limit(0);
// create socket
$socket = socket_create(AF_INET, SOCK_STREAM, 0) or die("Could not create socket\n");
// bind socket to port
$result = socket_bind($socket, $host, $port) or die("Could not bind to socket\n");
// start listening for connections
$result = socket_listen($socket, 3) or die("Could not set up socket listener\n");

// accept incoming connections
// spawn another socket to handle communication
$spawn = socket_accept($socket) or die("Could not accept incoming connection\n");
// read client input
$input = socket_read($spawn, 1024) or die("Could not read input\n");
// clean up input string
$input = trim($input);
echo "Client Message : ".$input;
// reverse client input and send back
$output = strrev($input) . "\n";
socket_write($spawn, $output, strlen ($output)) or die("Could not write output\n");
// close sockets
socket_close($spawn);
socket_close($socket);

کد client.php

$host    = "127.0.0.1";
$port    = 5353;
$message = "Hello Server";
echo "Message To server :".$message;
// create socket
$socket = socket_create(AF_INET, SOCK_STREAM, 0) or die("Could not create socket\n");
// connect to server
$result = socket_connect($socket, $host, $port) or die("Could not connect to server\n");  
// send string to server
socket_write($socket, $message, strlen($message)) or die("Could not send data to server\n");
// get server response
$result = socket_read ($socket, 1024) or die("Could not read server response\n");
echo "Reply From Server  :".$result;
// close socket
socket_close($socket);

پس از انجام تمام مراحل فوق باید روند زیر را جهت دریافت نتیجه انجام دهید:

۱) ابتدا این فایل‌ها را در دایرکتوری www موجود در WAMP یا htdocs موجود در Xampp کپی کنید.

۲) داخل فایل php.ini موجود در زمپ یا ومپ خود به دنبال عبارت extension=php_sockets.dll بگردید و سپس علامت ; را از ابتدای آن بردارید تا سوکت PHP شما فعال شود.

۳) مرورگر خود را باز کرده و آدرس localhost را تایب کنید.

۴) ابتدا فایل server.php را و سپس فایل client.php در مرورگر خود باز کنید.

در صورت مواجه شدن با خطای زیر مقدار عددی پورت را تغییر دهید. این مقدار می‌تواند بین ۱۰۲۴ تا ۶۵۵۳۵ باشد:

Warning: socket_bind(): unable to bind address [10048]: Only one usage of each socket address (protocol/network address/port) is normally permitted. in C:\xampp7\htdocs\socket\server.php on line 14
Could not bind to socket

به همین سادگی کار به اتمام می‌رسد و شما بین دو سوکت سرور و کلاینت (کاربر) اتصال برقرار کرده‌اید. امیدواریم این آموزش مورد پسند شما عزیزان واقع شده باشه و با انجام آن بتوانید گامی موثر در زمینه سوکت پروگرمینگ بردارید.

توجه: دوستان عزیز آموزش ویدیویی پی اچ پی (PHP) از مقدماتی تا پیشرفته به زبان فارسی + ساخت CMS مشابه وردپرس را می‌توانید با کلیک روی اینجا یاد بگیرید. (این دوره در حال برگزاری است)

آموزش مقدماتی تا پیشرفته PHP7 به همراه ساخت CMS اختصاصی مشابه وردپرس

نویسنده شوید

دیدگاه‌های شما (14 دیدگاه)

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

sima
28 مرداد 1399
آیا وب سوکت در هاست اشتراکی امکان پذیر است؟ منظورم ارسال فایل سمت سرور است. در نظر بگیرید که کاربری ثبت سفارش فروش زده است و همزمان نیاز است که سایر کاربران این ثبت را مشاهده کنند و در صورت نیاز قبول کنند. همین طور کاربر اول در جریان آن قرار گیرد و .... ممکن است توضیح دهید.

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

سهیل حیدری
08 آبان 1399
متاسفانه در هاست اشتراکی این امکان وجود نداره و شما باید vps تهیه کنید چون هاست اشتراکی فقط روی یک پورت اجرا میشه و سوکت در پی اچ پی بر روی پورت مجزا اجرا میشه من این مسئله رو کلی روش وقت گذاشتم و به نتیجه ای نرسیدم.

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

ردیاب aks
26 مرداد 1399
ممنون از سایت خوبتون

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

فلزیاب چست؟وچگونه کار میکند؟
26 مرداد 1399
عالی بود ممنون

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

خرید فلزیاب
26 مرداد 1399
عالیه

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

علی اکبر
06 فروردین 1398
سلام ابتدا باید تشکر کنم بابت این پست بسیار مفید و بعد بنده نفهمیدم دقیقا کاربرد سوکت چی هست. میشه بیشتر توضیح بدین؟ مثلا برای یک بازی آنلاین اندرویدی مثل دوز یا منچ یا ... چطور باید از این دستورات استفاده کرد؟ یا مثلا برای چت کردن کاربرانی که تو این مسابقه دارن با هم رقابت میکنن؟ اگه پروژه محور آموزش بدین یه دنیا ممنون میشیم.

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

احمد
18 آذر 1397
ممنون برای این مقاله ، عذر میخوان توی سوکت کاربرا چجوری باید تشخیص داده بشن، آیا خود سوکت پی اچ پی متدی برای احراز هویت کاربران داره؟ و دیگه اینکه آیا کار درستیه که یه کوئری به دیتابیس رو توی سوکت پیاده سازی کرد؟ به عنوان مثال وقتی فلان دیتا توسط کاربر A رکورد شد به کاربر B یه پیام بره

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

محمد رضا
03 آذر 1397
ممنون عالی بود

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

یک دوستار php
16 مهر 1397
سلام قالب خیلی شادی دارین ! - آدم خسته نمیشه واقعا عالیه.

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

مجید
29 خرداد 1397
سلام من فقط یک کانکشن میتونم باز کنم چطوری تعداد کلاینت رو بیشتر کنم ؟ ممنون

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

روکسو
30 خرداد 1397
سلام وقت بخیر شما می توانید با توسعه کدنویسی خود کانکشن های بیشتری را ایجاد کنید. فقط باید پورت های مورد نظر را که نیاز دارید آزاد کنید. مثلا پورت 4000 یا 4040

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

قیمت بیت کوین
05 خرداد 1397
مقاله خوبی بود ممنون

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

Milad
09 فروردین 1397
سلام، اگه بخوام روی هاست شخصی این کار رو انجام بدم، به چه صورت میشه؟ Php.ini قابل دسترسه؟

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

جواد
24 دی 1396
با سلام میشه بگید چطوری با ssl هماهنگش کنیم. وقتی که از ssl روی سایت استفاده می کنیم wss دیگه متصل نیمشه و خطا میده

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

عباس
10 دی 1396
سلام خسته نباشین .. خیلی مفید بود ممنون میشم در مورد توابع دیگه سوکت هم مقاله بدین ..

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

علیرضا
27 مرداد 1396
سلام استاد یک سوال ا خدمتتون داشتم و اون این که اصلا این برنامه نویسی سوکت php به چه کار من می اید من مباحث زیادی رو در php خوندم اما خیلی راحت میتونم از strres یا یک همچین چیزی برای برعکس کردن متن استفاده کنم خواهش میکنم بنده رو در نقاط قوت برنامه نویسی سوکت مخصوص php راهنمایی بفرمایید باتشکر

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

روکسو
04 شهریور 1396
با سلام و عرض ادب خدمت شما از برنامه نویسی سوکت برای ارتباط بین تجهیزات و همچنین ارتباط آنها با اینترنت استفاده می شود.

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.