Comet چیست! (3)

اینم کامیت به شکل Streaming

کد سمت سرور در فایلی بنام get_msg.php ذخیره شود:

<?php

header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Cache-Control: private, no-cache, must-revalidate, post-check=0, pre-check=0, max-age=0");
header('Pragma: private');
header("Pragma: no-cache");

header('Content-Type: text/html; charset=utf-8');

set_time_limit(0);

$msg_file='msg.txt';

for($i=0; $i<1024; $i++) echo ' ';

while(true) {

clearstatcache();
while(filesize($msg_file)==0) {
usleep(500000);
clearstatcache();
}

$fp=fopen($msg_file, "r+");
flock($fp, LOCK_EX);
$msg=fread($fp, filesize($msg_file));
ftruncate($fp, 0);
fclose($fp);

$msg=addslashes($msg);
$msg=str_replace("\n", '\n', $msg);
$msg=str_replace("\r", '', $msg);

echo '<script>parent.add_msg("', $msg, '");</script>';
@ ob_flush();
flush();

}

?>

چون ساختار کلی بخش سمت سرور برنامه خیلی شبیه به فایل روش Long polling هست فقط جاهایی رو توضیح میدم که با اون تفاوت دارن.
اولا که ما کل برنامه رو در یک while با شرط true گذاشتیم که الگوریتم برنامه پس از ارسال هر پیام دوباره از اول تکرار بشه.
ضمنا set_time_limit(0) باعث میشه تا زمان اجرای برنامه نامحدود باشه و دچار خطای Timeout نشه.

بوسیله خط for($i=0; $i<1024; $i++) echo ‘ ‘ تعداد کافی کاراکتر رو به مرورگرهایی مثل IE که برای شروع اجرا و نمایش محتویات نیاز به یک حداقل اولیه از کاراکترهای دریافت شده دارن ارسال میکنیم.

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

echo '<script>parent.add_msg("', $msg, '");</script>';
ob_flush();
flush();

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

کد صفحهء سمت کلاینت که صفحه ای است که در مرورگر اجرا میکنید:

<?php
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Cache-Control: private, no-cache, must-revalidate, post-check=0, pre-check=0, max-age=0");
header('Pragma: private');
header("Pragma: no-cache");

header('Content-Type: text/html; charset=utf-8');
?>
<html>
<head>
<script>

var txt;

function add_msg(msg) {
txt.value=parent.txt.value+"\n"+'received message: '+msg;
}

function load() {
txt=document.getElementById('txt');
txt.value='';
document.getElementById('comet_frame').src='get_msg.php';
}

</script>
</head>
<body onload="load();">
<center>
<span style="vertical-align: top">Messages:</span>
<textarea id="txt" style="width: 300; height: 300;"></textarea>
<iframe id="comet_frame" src="about:blank" style="display: none" />
</center>
</body>
</html>

فکر نمیکنم این کد ساده و کوتاه نیازی به توضیح خاصی داشته باشه.
تنها کار مهمی که میکنیم اینه که با تنظیم آدرس فریم داخلی به get_msg.php در سمت سرور، اجرای نامحدود get_msg.php رو موجب میشیم که هر بار که پیامی دریافت میکنه یک تگ و دستور جاوااسکریپت رو برای اجرا به مرورگر ارسال میکنه که باعث فراخوانی تابع add_msg که در صفحهء اصلی تعریف شده با پیام ارسال شده بعنوان آرگومان میگردد.

خب ظاهرا پیاده سازی روش Streaming ساده تر و کوتاهتر از روش Long polling بود، اما این فقط یک مثال ساده و ناقص هست برای نشان دادن الگوریتم کلی.
ضمنا توجه کنید که get_msg.php در پشت صحنهء وب سرور بصورت نامحدود اجرا میشه و بنابراین صفحهء سمت کلاینت رو برای هر بار تست بیش از یک بار اجرا نکنید چون باعث میشه علاوه بر پردازش get_msg.php قبلی یک پردازش جدید هم اضافه بشه و این دوتا در کار هم اختلال ایجاد میکنن.
ضمنا برای توقف یا ریستارت آپاچی راهی ندارید جز اینکه با استفاده از Task manager ویندوز پراسسهای آپاچی رو kill کنید.

یادتون نره باید پیامها رو بصورت دستی در فایل msg.txt وارد و سیو کنید (این فایل باید از قبل موجود باشه).

راستی این کدها:

$msg=addslashes($msg);
$msg=str_replace("\n", '\n', $msg);
$msg=str_replace("\r", '', $msg);

بخاطر این هستن که اگر پیام حاوی کاراکترهایی مثل کوتیشن و New line بود چون اینها موقعی که در رشته ای بعنوان آرگومان تابع جاوااسکریپت add_msg بصورت خام درج میشن باعث خطای سینتاکس در جاوااسکریپت میشن، ما اونها رو Escape میکنیم.

پاسخ دهید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

*

شما می‌توانید از این دستورات HTML استفاده کنید: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>