PHP while循环从数据库中提取

时间:2015-08-28 12:20:51

标签: php websocket

我正在使用websocket编写实时聊天应用程序。 我有一个函数检查数据库中是否有特定用户的新消息。 我仍然缺少的是一种无限调用此方法的方法,以便用户可以实时接收消息。

有没有办法运行后台循环或类似的东西可以做到这一点?

谢谢

3 个答案:

答案 0 :(得分:3)

您可以做的最糟糕的事情是将所有套接字设置为非阻塞。这将创建一个空闲循环,您的WS服务器将不断检查所有内容,将耗费您的CPU时间,完成任何有意义的事情,并让人们为您生气。

接下来最糟糕的事情是无限期阻止。这将要求客户定期发送数据,咀嚼带宽,没有任何意义,可能会在没有连接客户端的情况下将服务器置于挂起状态,并让人们生气。

相反,使用阻止,但设置超时。这是一种取决于您的系统的平衡行为,只有您可以决定超时的持续时间,希望通过一些数据来支持您的决定。

暂停的最佳位置是socket_select()。下面的代码将等待最多1秒的新数据包进入,当它变得无聊时,它将执行你的数据库。

define("SOCKET_TIMEOUT", 1);

function tick() { /* Put your DB checking here. */ }

while (true) {
    $read = get_array_of_sockets_that_may_have_sent_a_packet();
    $write = $except = null; // We probably don't care about these.
    tick();
    $number_of_sockets_ready = socket_select($read, $write, $except, SOCKET_TIMEOUT);
    if ($number_of_sockets_ready === false) { ... } /* Something went horribly wrong. socket_strerror(socket_last_error()) is your friend here. */ 
    elseif ($number_of_sockets > 0) {
        // At least one socket is ready for socket_recv() or socket_read(). Do your magic here!
    }
}

请注意,超时并不能保证每秒都会调用tick(),或者每秒只调用一次。如果数据包立即进入,并且处理得很琐碎,那么在调用tick()之间可能只有几毫秒。另一方面,如果有几个数据包进入并且处理每个数据包并不容易,那么再次调用tick()之前可能需要几秒钟。

答案 1 :(得分:2)

我首选的方法是通过简单的setTimeout()调用来反复检查服务器是否有新消息。

var checkForNewMessages = window.setTimeOut(function(){
    $.ajax({
        url: 'getChatUpdates.php', 
        type: 'POST',
        data: {user_id: '<?php echo $_SESSION['user_id']; ?>' }
    }).done(function(r){
        // do stuff to display new messages here
    });
}, 5000);

如评论中所述,根据应用程序的体系结构,在源代码中显示用户ID可能是也可能不是安全问题。如果是这样,另一种选择是为您的用户生成一次性唯一标识符。我个人不会,但就像我说的,这取决于你设置的架构。

无论如何,理论上,您可以从服务器端脚本生成GUID并将其传递给您的AJAX,然后让ajax在其下一次调用中使用GUID。每次调用GUID都会随着未经通知的人无法简单地复制该ajax请求而改变。

更简单的方法可能是从会话服务器端获取user_id,而不是将其作为参数传递。

答案 2 :(得分:0)

我自己从未建造过这样的东西。但是如何编写一个轮询数据库然后推送消息的常规脚本(我认为理想情况下这些应该是单独的组件)并设置一个以您想要的频率运行此脚本的计划任务。

在架构上,这可能不是最优雅的解决方案,因为你也会发现人们在这里围绕类似的问题和相关命题进行辩论:Invoking a PHP script from a MySQL trigger

但是看看你如何问你的问题以及你的设置表明了什么,这可能是一个开始。