تابع stream_get_meta_data() در PHP
تابع stream_get_meta_data() یکی از توابع مفید در PHP برای دریافت اطلاعات متادیتا دربارهٔ یک stream resource است. این تابع اطلاعاتی مانند نوع استریم، آیا قابل جستجو (seekable) است یا نه، وضعیت EOF، وضعیت بلوک/non-blocking، تایماوت و مقادیر مربوط به wrapper را برمیگرداند. این اطلاعات در برنامههای شبکهای، کار با فایلها و استریمهای رمزنگاریشده کاربردی و ضروریاند.
نحوه فراخوانی و مقدار بازگشتی
تابع به شکل زیر فراخوانی میشود:
$meta = stream_get_meta_data($stream);خروجی یک آرایهٔ انجمنی (associative array) است که کلیدهای رایج آن عبارتاند از:
| کلید | توضیح |
|---|---|
| timed_out | آیا آخرین عملیات با تایماوت مواجه شده بود (true/false) |
| blocked | آیا استریم در حالت بلاکینگ است (true/false) |
| eof | پایان فایل یا استریم رسیده است یا نه (true/false) |
| unread_bytes | تعداد بایتهایی که هنوز خوانده نشدهاند (در برخی wrapperها) |
| stream_type | نوع سطح پایین استریم (مثلاً “STDIO” یا “tcp_socket/0”) |
| wrapper_type | نوع wrapper (مثلاً “plainfile”, “http”) |
| wrapper_data | دادهٔ مرتبط با wrapper (بسته به نوع wrapper متفاوت است) |
| mode | حالت باز شدن استریم (مثلاً “r”, “w+”) |
| seekable | آیا استریم قابل seek است یا خیر |
مثال پایه: فایل محلی
$fp = fopen('example.txt', 'r');
$meta = stream_get_meta_data($fp);
var_dump($meta);
fclose($fp);در این مثال تابع اطلاعاتی مانند mode، wrapper_type و seekable را برمیگرداند. این برای تصمیمگیری دربارهٔ خواندن یا استفاده از fseek کاربردی است.
نمونه کاربرد در برنامههای شبکه: تشخیص تایماوت
$fp = stream_socket_client("tcp://example.com:80", $errno, $errstr, 5);
if (!$fp) {
echo "Error: $errstr ($errno)n";
} else {
stream_set_timeout($fp, 2); // ست کردن تایماوت خواندن
fwrite($fp, "GET / HTTP/1.0rnHost: example.comrnrn");
$data = '';
while (!feof($fp)) {
$chunk = fread($fp, 1024);
if ($chunk === false) break;
$data .= $chunk;
$meta = stream_get_meta_data($fp);
if ($meta['timed_out']) {
echo "Read timed outn";
break;
}
}
fclose($fp);
}در این کد، با استفاده از stream_set_timeout تایماوت برای خواندن تنظیم میشود و پس از هر fread متادیتا بررسی میشود تا اگر تایماوت اتفاق افتاده برنامه واکنش مناسب (مثلاً قطع اتصال یا لاگ گرفتن) انجام دهد.
توضیح تخصصی درباره کلیدها و نکات مهم
- timed_out: تنها نشان میدهد آیا آخرین عملیات I/O به دلیل تایماوت خاتمه یافته است. برای تشخیص دسترسی یا سلامت اتصال مناسب است.
- blocked: اگر false باشد، استریم در حالت non-blocking است؛ در این حالت باید از stream_select برای مدیریت I/O استفاده کنید.
- unread_bytes: مقدار وابسته به پیادهسازی wrapper است و در همهٔ استریمها مقدار قابل اتکایی نیست.
- wrapper_data: مثلاً برای wrapperهای HTTP این قسمت حاوی هدرهای دریافتی یا اطلاعاتی است که wrapper ارائه میدهد.
- seekable: اگر false باشد، توابعی مانند fseek و ftell کاربرد ندارند (مثلاً برای اکثر سوکتها).
مثال: استفاده با php://temp و بررسی seekable
$s = fopen('php://temp', 'w+');
fwrite($s, "Hello World");
rewind($s);
$meta = stream_get_meta_data($s);
echo "Seekable: " . ($meta['seekable'] ? 'yes' : 'no') . PHP_EOL;
fclose($s);در این مثال از php://temp استفاده میکنیم که معمولاً seekable است، بنابراین میتوانیم محتوا را بازخوانی یا جابجا کنیم.
پیتفولها و نکات عملی
- stream_get_meta_data اطلاعات وضعیت لحظهای را میدهد؛ برای مانیتورینگ پیوسته باید مرتب آن را فراخوانی کنید.
- برای تشخیص وقوع timeout میان عملیات خواندن، بهتر است پس از هر عملیات I/O متادیتا را چک کنید.
- خواندن مستقیم از کلید wrapper_data یا unread_bytes برای تمام استریمها قابل اتکا نیست؛ مستندات PHP را برای هر wrapper بررسی کنید.
- برای مدیریت غیرهمزمان (async) یا event-driven بهتر است از stream_select یا extensionهای مخصوص (مانند libevent یا Swoole) استفاده کنید.
مقایسه با توابع مشابه و جایگزینها
- feof(): فقط پایان فایل را بررسی میکند، در حالی که stream_get_meta_data مقدار جامعتری از وضعیت استریم میدهد.
- stream_get_contents(): برای گرفتن محتوای باقیمانده مفید است اما اطلاعات وضعیت را ارائه نمیدهد.
- stream_select(): برای مانیتورینگ چند استریم همزمان مناسبتر از فراخوانی مکرر stream_get_meta_data است.
خلاصه و بهترین شیوهها
تابع stream_get_meta_data یک ابزار ساده و قدرتمند برای بهدست آوردن وضعیت استریم در PHP است. برای تشخیص تایماوت، بررسی امکان seek، و فهم نوع wrapper بسیار مفید است. با این حال نباید به همهٔ مقادیر آن بهعنوان حقیقت مطلق تکیه کنید؛ برخی کلیدها وابسته به نوع wrapper هستند. در برنامههای شبکهای، ترکیب stream_get_meta_data با stream_set_timeout، stream_select و مدیریت صحیح بلوکینگ بهترین نتیجه را میدهد.
در نهایت همواره مستندات رسمی PHP را بررسی کنید تا از جزئیات نسخهای و ویژگیهای خاص هر wrapper مطلع شوید.
آیا این مطلب برای شما مفید بود ؟




