我有一個PHP CLI腳本,主要寫作功能作爲聊天客戶端連接到聊天服務器(不要問我爲什麼我這樣做在PHP中,這是另一個故事哈哈)。PHP:pcntl_alarm()和socket_select()可以和平地存在於同一個線程中嗎?
我的腳本利用socket_select()函數來掛起執行,直到套接字上發生什麼事,然後喚醒,處理事件並等待下一個事件。現在,我需要每30秒左右執行一些例行任務(檢查是否需要取消配額管理,保存用戶數據庫和其他各種配件)。
從我所知道的,PHP並沒有很好的多線程支持。我的第一個想法是每次套接字生成一個事件並重新獲得程序時,比較一個時間戳,但這是非常不一致的,因爲服務器可能會閒置幾個小時,並且沒有執行任何清理例程。
我遇到了PHP pcntl擴展,它讓我使用SIGALRM分配一個時間間隔來獲取發送,並在每次發送函數時執行該函數。這似乎是我的問題的理想解決方案,但pcntl_alarm()和socket_select()彼此衝突非常糟糕。每次SIGALRM被觸發時,各種瘋狂的事情都發生在我的套接字控制代碼中。
我的程序相當長,所以我不能在這裏發佈它,但它不應該因爲我不相信我在代碼方面做錯了什麼。我的問題是:在等待的socket_select()中,是否有任何方法可以在同一個線程中處理SIGALRM?如果是這樣,怎麼樣?如果不是,我在這裏有什麼替代方案?
這是我的程序的一些輸出。我的報警功能只是輸出「Tick!」每當它被稱爲讓事情發生的時候很容易知道。這是輸出(包括錯誤)允許它剔4倍後(沒有實際嘗試在連接到服務器,儘管它說什麼):
[10年5月28日20時01分05秒@ ]聊天服務器從文件啓動192.168.1.28端口4050
[10年5月28日20時01分05秒@]加載用戶
PHP公告:未定義抵消:0在/ home /丹尼/項目/PHPChatServ/ChatServ.php 112行
PHP警告:socket_select():無法選擇[4]:在/ home/danny/pr中斷系統調用Ojects/PHPChatServ/ChatServ.php on line 116
[05-28-10 @ 20:01:15]勾號!
PHP警告:socket_accept():無法接受傳入的連接[4]:中斷系統調用在/home/danny/projects/PHPChatServ/ChatServ.php線126
[10年5月28日@ 20:01:25]滴答! PHP警告:socket_getpeername()期望參數1是資源,在/home/danny/projects/PHPChatServ/ChatServ.php在線129給出的布爾值
[05-28-10 @ 20:01:25]接受從 PHP通知套接字連接:未定義偏移:1 /home/danny/projects/PHPChatServ/ChatServ.php線112上
PHP警告:socket_select():無法選擇[4]:在被中斷的系統呼叫/ home/danny/projects/PHPChatServ/ChatServ.php on line 116
[05-28-10 @ 20:01:35] Tick!
PHP警告:socket_accept():無法接受傳入的連接[4]:中斷系統調用在/home/danny/projects/PHPChatServ/ChatServ.php線126
[10年5月28日@ 20:01:45]請勾選!
PHP警告:socket_getpeername()預計參數1是資源,布爾線在給定/home/danny/projects/PHPChatServ/ChatServ.php 129
[10年5月28日20:01 @: 45]從
PHP通知接受插座連接:未定義偏移:2 /home/danny/projects/PHPChatServ/ChatServ.php線112上
我相信tv_sec參數對我正在做的事很好 – DWilliams 2010-08-16 14:01:30