ویژگی تصویر

تابع stream_socket_get_name() در PHP

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

در توسعه شبکه‌ای با PHP، گاهی لازم است آدرس طرف مقابل (کلاینت) یا آدرس محلی یک اتصال را به دست بیاوریم. برای این منظور PHP تابع stream_socket_get_name() را فراهم می‌کند که روی streamهای مبتنی بر سوکت کار می‌کند. این تابع ساده اما کاربردی در لاگ‌گذاری، کنترل دسترسی و نمایش اطلاعات اتصال بسیار مفید است.

امضای تابع و پارامترها

امضای تابع به صورت زیر است:

stream_socket_get_name(resource $stream, bool $want_peer): string|false

توضیح پارامترها:

  • $stream — یک resource متعلق به stream که از توابعی مانند stream_socket_server، stream_socket_accept یا stream_socket_client برمی‌گردد.
  • $want_peer — اگر true باشد، نام (آدرس) طرف مقابل (peer) بازگردانده می‌شود؛ اگر false باشد، نام محلی (local) برگردانده می‌شود.

خروجی تابع

در صورت موفقیت تابع یک رشته برمی‌گرداند و در صورت خطا مقدار false. فرمت رشته معمولاً برای TCP/UDP به شکل IP:PORT است و برای Unix domain sockets مسیر فایل نمایان می‌شود. برای IPv6 ممکن است خروجی به صورت [::1]:PORT باشد.

مثال عملی — سرور ساده با ثبت آدرس کلاینت

<?php
$server = stream_socket_server("tcp://127.0.0.1:9000", $errno, $errstr);
if (!$server) {
    die("Unable to create server: $errstr ($errno)n");
}

while ($conn = @stream_socket_accept($server)) {
    $peer = stream_socket_get_name($conn, true); // آدرس کلاینت
    $local = stream_socket_get_name($conn, false); // آدرس محلی
    echo "Connected: peer=$peer, local=$localn";
    fwrite($conn, "Hello from servern");
    fclose($conn);
}
?>

توضیح: این کد یک سرور TCP روی پورت 9000 ایجاد می‌کند. پس از پذیرش هر اتصال، با استفاده از stream_socket_get_name هم آدرس کلاینت (peer) و هم آدرس محلی را می‌گیرد و سپس پیامی برای کلاینت می‌فرستد. اگر ایجاد سرور ناموفق باشد پیام خطا نمایش داده می‌شود.

مثال کلاینت — مشاهده آدرس محلی و سرور متصل‌شده

<?php
$client = stream_socket_client("tcp://127.0.0.1:9000", $errno, $errstr, 5);
if (!$client) {
    die("Unable to connect: $errstr ($errno)n");
}

$remote = stream_socket_get_name($client, true);   // آدرس سرور (peer)
$local  = stream_socket_get_name($client, false);  // آدرس محلی (local)
echo "Remote: $remotenLocal: $localn";

echo fgets($client);
fclose($client);
?>

توضیح: این مثال یک کلاینت می‌سازد که به سرور محلی روی پورت 9000 متصل می‌شود. سپس با stream_socket_get_name آدرس سرور و آدرس محلی را نمایش می‌دهد. این اطلاعات برای لاگ و تشخیص پورت‌های ephemeral مفید است.

نکات مربوط به IPv6 و پردازش دقیق آدرس و پورت

در برخورد با IPv6 باید مراقب باشید چون آدرس‌ها خود شامل : هستند. خروجی معمولاً به صورت [IPv6]:PORT یا گاهی بدون کروشه خواهد بود. برای جدا کردن آدرس از پورت از روش امن زیر استفاده کنید:

<?php
function splitAddressPort(string $name): array {
    // name ممکن است: 127.0.0.1:1234 یا [::1]:1234 یا unix:///path
    if (strpos($name, 'unix:') === 0 || strpos($name, '/')) {
        return [$name, null]; // مسیر یونیکس یا رشته‌ای دیگر
    }

    if (strpos($name, '[') === 0) {
        // [IPv6]:PORT
        $pos = strpos($name, ']');
        $ip = substr($name, 1, $pos - 1);
        $port = substr($name, $pos + 2);
        return [$ip, (int)$port];
    }

    // IPv4 or plain host:port
    $pos = strrpos($name, ':');
    if ($pos !== false) {
        $ip = substr($name, 0, $pos);
        $port = substr($name, $pos + 1);
        return [$ip, (int)$port];
    }

    return [$name, null];
}

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

موارد استفاده عملی و نکات امنیتی

  • لاگ‌گذاری آدرس کلاینت برای بررسی ترافیک و اشکال‌زدایی.
  • محدودسازی دسترسی بر اساس آدرس آی‌پی (ACL) قبل از پردازش درخواست‌ها.
  • استفاده در تست‌ها برای مشاهده پورت‌های ephemeral که سیستم عامل تخصیص می‌دهد.
  • در UDP: اگر سوکت به صورت connectionless باشد، ممکن است آدرس peer تنها پس از دریافت بسته مشخص شود یا اطلاعات لازم را نداشته باشید.

مقایسه با توابع مرتبط

تابعکاربرد
stream_socket_get_name()دریافت نام محلی یا آدرس peer برای streamهای مبتنی بر سوکت
socket_getpeername()همان کار برای منابع ext-sockets (سویکت‌های سطح پایین)
stream_socket_enable_crypto()فعال‌سازی SSL/TLS روی streamها (ممکن است آدرس تغییری نکند ولی نحوه دسترسی متفاوت است)

خطاها و نکات عملیاتی

  • اگر stream معتبر نباشد یا اتصال برقرار نشده باشد، تابع false برمی‌گرداند.
  • در صورتی که دسترسی به اطلاعات سوکت محدود شده باشد یا سوکت در حالت خاصی باشد، ممکن است اطلاعات کامل را دریافت نکنید.
  • برای UDP و سوکت‌های connectionless ممکن است تنها پس از stream_socket_recvfrom آدرس peer واضح شود.

خلاصه و توصیه‌های نهایی

تابع stream_socket_get_name() یک ابزار ساده و قدرتمند برای به‌دست آوردن آدرس‌های مرتبط با streamهای مبتنی بر سوکت در PHP است. با توجه به تفاوت‌های IPv4/IPv6 و یونیکس سوکت‌ها، بهتر است همیشه خروجی را به‌صورت امن پارس کنید و در صورت نیاز از بررسی‌های اضافی برای امنیت و لاگ‌برداری استفاده نمایید.

در پروژه‌های واقعی، ترکیب این تابع با منطق احراز هویت، لیست سیاه/سفید و ثبت رویدادها می‌تواند به بهبود امنیت و قابلیت ردیابی کمک کند.

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

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