ویژگی تصویر

تابع ip2long() در PHP

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

تابع ip2long() در PHP برای تبدیل آدرس IPv4 به یک عدد صحیح (32‑بیتی) استفاده می‌شود. این تبدیل برای ذخیره‌سازی بهینه در دیتابیس، مقایسه‌ی سریع آدرس‌ها و انجام عملیات بیت‌به‌بیتی مثل تشخیص شبکه و محدوده‌ها بسیار کاربردی است. در این مقاله به صورت کامل رفتار، نکات فنی، مثال‌های عملی و جایگزین‌های مناسب برای IPv6 را بررسی می‌کنیم.

سینتکس و مقدار بازگشتی

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

ip2long(string $ip): int|false

توضیح: اگر ورودی یک آدرس IPv4 معتبر باشد، مقدار عددی 32‑بیتی (int) برگردانده می‌شود. در صورت نامعتبر بودن آدرس، false بازمی‌گردد. روی سیستم‌های 32‑بیتی مقدار ممکن است منفی شود؛ برای دریافت مقدار بدون علامت باید از تبدیل به unsigned استفاده کرد.

مثال پایه‌ای

<?php
$ip = '192.168.1.10';
$long = ip2long($ip);
var_dump($long); // e.g. int(3232235786)

echo long2ip($long); // "192.168.1.10"
?>

توضیح: در این مثال، ip2long مقدار عددی معادل IPv4 را تولید می‌کند و long2ip عکس این تبدیل را انجام می‌دهد. توجه کنید که روی برخی سیستم‌ها مقدار بازگشتی ممکن است به صورت عدد منفی نمایش داده شود (بخاطر نمایش signed int).

مقادیر منفی و ذخیره‌سازی امن در دیتابیس

یک نکته عملی بسیار مهم: روی سیستم‌های 32‑بیتی، ip2long ممکن است مقدار منفی بدهد. برای ذخیره‌سازی در ستون INT UNSIGNED در MySQL باید مقدار بدون علامت را بسازید:

$ip = '255.255.255.255';
$long = ip2long($ip);
$unsigned = sprintf('%u', $long); // convert to unsigned string
// Now store $unsigned into an INT UNSIGNED column

توضیح: sprintf(‘%u’, …) مقادیر منفی را به نمایش بدون علامت معادل‌شان تبدیل می‌کند. این روش کمک می‌کند هنگام ذخیره و ایندکس‌گذاری، ترتیب و مقایسه‌ها درست انجام شوند.

مثال: جستجوی آی‌پی در یک رنج (CIDR)

برای بررسی اینکه یک آی‌پی در محدوده‌ی شبکه با CIDR قرار دارد می‌توان از عملگرهای بیت‌به‌بیتی استفاده کرد:

function ip_in_range($ip, $network, $cidr) {
    $ipLong = ip2long($ip);
    $netLong = ip2long($network);
    $mask = -1 << (32 - $cidr); // create mask
    return ($ipLong & $mask) === ($netLong & $mask);
}

// usage
var_dump(ip_in_range('192.168.1.5', '192.168.1.0', 24)); // true

توضیح: در این تابع، ابتدا آدرس‌ها را به long تبدیل کرده، سپس ماسک را با شیفت بیت می‌سازیم و با عملیات AND بررسی می‌کنیم که آیا آدرس در شبکه هست یا نه. دقت کنید که روی سیستم‌های 32‑بیتی باید به مسئله‌ی signed بودن اعداد توجه کنید یا از راهکار unsigned استفاده کنید.

مثال جدول: ورودی‌ها و خروجی‌های نمونه

آدرسip2long()شرح
0.0.0.00اولین مقدار ممکن
127.0.0.12130706433لوپ‌بک محلی
192.168.1.103232235786شبکه خصوصی
255.255.255.255-1 or 4294967295در 32‑بیتی ممکن است -1 نمایش یابد

اشکالات و مراقبت‌های امنیتی

  • قبل از ip2long از filter_var با FLAG_IPV4 استفاده کنید: filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4).
  • مطمئن شوید مقادیر بازگشتی را چک می‌کنید؛ ip2long در موارد نامعتبر false برمی‌گرداند.
  • برای ذخیره حتماً از مقدار unsigned استفاده کنید تا در مقایسه‌ها و مرتب‌سازی مشکلی ایجاد نشود.
  • برای ورودی‌های کاربر همیشه sanitization و validation انجام دهید تا حملات جعل IP یا header spoofing کاهش یابد.

محدودیت‌ها و جایگزین‌ها برای IPv6

تابع ip2long تنها IPv4 را پشتیبانی می‌کند. برای IPv6 باید از توابع inet_pton و inet_ntop استفاده کنید که باینری آدرس را به رشته و برعکس تبدیل می‌کنند. برای ذخیره‌سازی IPv6 معمولاً از ستون‌های VARBINARY(16) یا CHAR(39) استفاده می‌شود.

// IPv6 example using inet_pton and unpack/pack
$ipv6 = '2001:0db8:85a3::8a2e:0370:7334';
$packed = inet_pton($ipv6); // 16-byte binary
$hex = bin2hex($packed); // hexadecimal representation for storage or comparison

// back to human readable
$unpacked = inet_ntop(hex2bin($hex));

توضیح: inet_pton تبدیل به فرم باینری می‌کند که می‌توان آن را به صورت hex در دیتابیس ذخیره و سپس با inet_ntop دوباره رشته قابل خواندن را بازیابی کرد. برای مقایسه‌ی عددی IPv6 نیاز به کتابخانه‌هایی مانند GMP یا استفاده از رشته‌ی hex و مقایسه‌های بایت به بایت است.

بهینه‌سازی‌ها و نکات عملی

  • برای سرعت جستجو در دیتابیس، ستون IP عددی را به عنوان ایندکس قرار دهید (INT UNSIGNED برای IPv4، VARBINARY(16) برای IPv6).
  • برای محاسبات شبکه از توابع بیت‌به‌بیتی استفاده کنید و از محاسبه‌ی ماسک به صورت آماده (precomputed) بهره ببرید.
  • اگر در سروری با معماری 32‑بیتی کار می‌کنید، بهتر است سرور را به 64‑بیتی مهاجرت دهید یا همواره از sprintf(‘%u’, …) برای تبدیل به unsigned استفاده کنید.

خلاصه و جمع‌بندی

تابع ip2long ابزاری ساده و قدرتمند برای تبدیل IPv4 به عدد و انجام مقایسه‌ها و ذخیره‌سازی بهینه است. با این حال باید به محدودیت‌های سیستم (32‑بیتی) و عدم پشتیبانی از IPv6 توجه داشت. ترکیب ip2long با validation مناسب، تبدیل unsigned برای ذخیره، و استفاده از inet_pton برای IPv6 باعث می‌شود مدیریت آدرس‌ها هم ایمن‌تر و هم سریع‌تر انجام شود.

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

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