ویژگی تصویر

تابع gethostbynamel() در PHP

  /  PHP   /  تابع gethostbynamel() در PHP
بنر تبلیغاتی الف
آموزش PHP

تابع gethostbynamel() در PHP برای تبدیل یک نام میزبان (hostname) به لیستی از آدرس‌های IPv4 استفاده می‌شود. این تابع زمانی مفید است که بخواهید تمام رکوردهای A یک دامنه را دریافت کنید یا از بین چند آدرس موجود انتخاب کنید.

خلاصه عملکرد

  • ورودی: یک رشته (نام میزبان یا دامنه).
  • خروجی: آرایه‌ای از آدرس‌های IPv4 (به صورت رشته) یا false در صورت خطا.
  • محدودیت: فقط رکوردهای A (IPv4) را بازمی‌گرداند — رکوردهای AAAA (IPv6) را شامل نمی‌شود.

امضا و مقدار بازگشتی

تابع به شکل زیر استفاده می‌شود:

array|false gethostbynamel ( string $hostname )

در جدول زیر فرمت خروجی را خلاصه کرده‌ایم:

ورودیخروجی
مثلاً “example.com”[“93.184.216.34”] یا چند آی‌پی در صورت وجود، یا false

مثال ساده

<?php
$host = "example.com";
$ips = gethostbynamel($host);

if ($ips === false) {
    echo "Resolve failed for $hostn";
} else {
    foreach ($ips as $ip) {
        echo "IP: $ipn";
    }
}
?>

این کد نام دامنه را به IP تبدیل می‌کند و هر آدرس را چاپ می‌کند. اگر عملیات پرازش (resolve) ناموفق باشد، پیام خطا نمایش داده می‌شود.

چرا چند آدرس ممکن است برگردانده شود؟

یک دامنه ممکن است چند رکورد A داشته باشد (DNS round-robin، چند سرور، توزیع بار). به همین دلیل gethostbynamel تمام آدرس‌های IPv4 قابل دسترس را در قالب یک آرایه بازمی‌گرداند.

موارد کاربردی و نکات عملی

  • توزیع بار و چک کردن همه سرورها: وقتی می‌خواهید وضعیت یا سلامت هر سرور پشت یک نام دامنه را بررسی کنید.
  • اتصال مستقیم به IP: گاهی لازم است یک اتصال شبکه مستقیم به هر آدرس برقرار شود (مثلاً برای تست latency).
  • اعمال قوانین فایروال/ACL: استخراج لیست آدرس‌ها برای وارد کردن به قوانین دسترسی.

محدودیت‌ها و نکات ایمنی

  • توجه: تابع فقط آدرس‌های IPv4 را بازمی‌گرداند. برای پشتیبانی از IPv6 از توابع دیگری مانند dns_get_record یا افزونه‌های socket استفاده کنید.
  • نتایج تابع به resolver سیستم (مثلاً libc) وابسته است؛ بنابراین فایل /etc/hosts، DNS cache یا تنظیمات سیستم می‌تواند بر خروجی اثر بگذارد.
  • در محیط‌های با DNS ناامن، به احتمال جعل (DNS spoofing) توجه کنید و در موارد حساس از DNSSEC یا کانال‌های امن استفاده کنید.

جایگزین‌ها و روش‌های تکمیلی

برای دریافت هر دو نوع رکورد (A و AAAA) یا جزئیات بیشتر می‌توانید از dns_get_record() استفاده کنید.

<?php
$host = "example.com";
$records = dns_get_record($host, DNS_A + DNS_AAAA);

$ips = [];
foreach ($records as $r) {
    if (isset($r['type']) && $r['type'] === 'A') {
        $ips[] = $r['ip'];
    } elseif (isset($r['type']) && $r['type'] === 'AAAA') {
        $ips[] = $r['ipv6'];
    }
}

print_r($ips);
?>

در این کد، رکوردهای A و AAAA با هم جمع‌آوری می‌شوند و آرایه‌ای تک که شامل هر دو نوع آدرس است ساخته می‌شود. این راهکار مناسب زمانی است که به پشتیبانی از IPv6 نیاز دارید.

الگوریتم پیشنهادی: fallback و اعتبارسنجی

در عمل بهتر است ابتدا از gethostbynamel استفاده کنید و در صورت شکست به dns_get_record یا ابزارهای دیگر fallback کنید. همچنین بهتر است آدرس‌ها را اعتبارسنجی کنید.

<?php
function resolveHostAll($host) {
    $ips = @gethostbynamel($host);
    if ($ips === false) {
        // fallback to dns_get_record for broader support
        $records = @dns_get_record($host, DNS_A + DNS_AAAA);
        $ips = [];
        if ($records !== false) {
            foreach ($records as $r) {
                if ($r['type'] === 'A' && !empty($r['ip'])) {
                    $ips[] = $r['ip'];
                } elseif ($r['type'] === 'AAAA' && !empty($r['ipv6'])) {
                    $ips[] = $r['ipv6'];
                }
            }
        }
    }
    // unique and validate
    $ips = array_values(array_unique($ips));
    return $ips;
}
?>

این تابع ابتدا سعی می‌کند با gethostbynamel نتیجه بگیرد، در غیر این صورت با dns_get_record ادامه می‌دهد. در انتها مقادیر تکراری حذف و لیست بازگردانده می‌شود.

عملکرد، کشینگ و زمان پاسخ

عملیات DNS می‌تواند زمان‌بر باشد؛ بنابراین در درخواست‌های پرتعداد بهتر است از cache محلی استفاده کنید یا رزولوشن را در لایه‌ای جدا (مثلاً یک سرویس میکروسرویس یا cache) انجام دهید. تابع gethostbynamel خود cache داخلی PHP ندارد و به resolver سیستم متکی است.

نمونه‌های پیشرفته و نکات تکمیلی

  • برای بررسی reachability از هر IP می‌توانید از fsockopen یا stream_socket_client استفاده کنید.
  • برای زمان‌بندی یا timeout سفارشی هنگام resolve بهتر است از توابع غیرهمزمان یا اجرای resolve در پروسس جدا استفاده کنید.
  • در محیط‌های container یا سرورهای با DNS خاص، نتیجه تابع ممکن است متفاوت باشد؛ از ابزارهای خط فرمان مثل dig یا nslookup نیز برای عیب‌یابی استفاده کنید.

خلاصه و بهترین شیوه

gethostbynamel تابع ساده و مفیدی برای دریافت رکوردهای A و آدرس‌های IPv4 است. اما برای پشتیبانی از IPv6 و اطلاعات کامل‌تر بهتر است از dns_get_record استفاده کنید و همیشه رفتار را در محیط هدف تست کنید. از cache محلی و مکانیزم‌های fallback استفاده کنید تا پایداری و سرعت برنامه افزایش یابد.

آیا این مطلب برای شما مفید بود ؟

خیر
بله
موضوعات شما در انجمن: