簡體   English   中英

PHP套接字綁定/偵聽在方法(類)中使用時不起作用

[英]PHP socket bind/listen are not working when used in method (class)

我想為幾個cron作業實現一個簡單的鎖定機制,因此決定以不同尋常的方式進行。 在套接字創建/綁定/監聽方面,PHP似乎有點bug。

起作用的代碼:

<?php
echo 'EXECUTING: '. __METHOD__ . \PHP_EOL;

if(false === ($socket = \socket_create(\AF_INET, \SOCK_STREAM, \SOL_TCP))) {
    die('create');
}

if(false === ($bind = \socket_bind($socket, '127.0.0.1', 4444))) {
    die('bind');
}

if(false === ($listen = \socket_listen($socket))) {
    die('listen');
}

var_dump($socket, $bind, $listen);

這將創建一個套接字,將其綁定到接口以等待傳入連接。 您可以通過調用以下內容進行檢查:

netstat -anp | grep LIST | grep tcp

如果您使用相同的PHP代碼並將其放入簡單的類中,則不會綁定/監聽。 這是我正在談論的代碼:

<?php

class Test
{
    public function lock()
    {
        echo 'EXECUTING: '. __METHOD__ . \PHP_EOL;

        if(false === ($socket = \socket_create(\AF_INET, \SOCK_STREAM, \SOL_TCP))) {
            die('create');
        }

        if(false === ($bind = \socket_bind($socket, '127.0.0.1', 4444))) {
            die('bind');
        }

        if(false === ($listen = \socket_listen($socket))) {
            die('listen');
        }

        var_dump($socket, $bind, $listen);
    }
}

$t = new Test();
$t->lock();

echo 'Working...'. \PHP_EOL;
sleep(60);
echo 'Done.';

執行此代碼,您將看到var_dump會說:

  1. $socket是一種資源(這就是我們想要的)
  2. $bind = true
  3. $listen = true

但是代碼實際上沒有綁定/監聽。

我做錯了什么?

編輯:

經過測試:

  • PHP 5.4.4(Linux)
  • PHP 5.3.3(Linux)

答案很簡單: $socket變量是一個局部變量 ,沒有引用,而是在方法范圍內。 這意味着,一旦方法被執行,PHP將銷毀所有局部變量-因此$socket也是如此。 您成功創建了套接字,然后PHP在同一時間取消了它的設置(因為方法結束了它的執行)。 請注意,取消設置局部變量並不意味着立即釋放內存。 垃圾收集周期很昂貴,因此PHP僅在達到內存限制時才這樣做。

要了解差異,請在創建套接字后將sleep()調用放入方法內部。 PHP從5.3版本開始就進行了垃圾回收 ,因此您嘗試使用的版本會受到影響。 要實時觀看,可以查看以下代碼段

class Foo
{

    public function __destruct()
    {
        echo('destroyed'.PHP_EOL);
    }
}

class Bar
{
    public function test()
    {
        echo('starting method'.PHP_EOL);
        $obj = new Foo();
        echo('ending method'.PHP_EOL);
    }
}
echo('start script'.PHP_EOL);
$obj = new Bar;
$obj->test();
echo('end script'.PHP_EOL);

結果

start script
starting method
ending method
destroyed
end script

-如您所見,在退出方法調用后,幾乎立即調用了類析構函數,因為本地$obj變量在其他任何地方都沒有引用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM