[英]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會說:
$socket
是一種資源(這就是我們想要的) $bind = true
$listen = true
但是代碼實際上沒有綁定/監聽。
我做錯了什么?
編輯:
經過測試:
答案很簡單: $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.