简体   繁体   English

如何使用ajax显示在线用户

[英]How to show online users with ajax

I'm want to show all the users that are online, in real-time on my website. 我想在我的网站上实时显示所有在线用户。 Not sure how to go about this though. 不知道如何解决这个问题。 It can't be hard to add new users once they log in, but I'll also need to remove users that are not logged in anymore. 登录后添加新用户并不困难,但我还需要删除未登录的用户。

Any idea how to do this? 知道怎么做吗? Should I check with jQuery what users have loged off and remvove them from the list etc? 我应该用jQuery检查用户已经删除了什么并从列表中删除它们等?

Your problem is going to be people navigating away without logging out, their session will still exist for how ever long you have the timeout set before their session data is subject to collection (actually possibly much longer) 您的问题将是人们在没有退出的情况下导航,他们的会话仍将存在,因为您的会话数据需要收集之前设置超时(实际上可能更长)

To get a truly accurate count of who is logged in and visiting the site you will need each client to send a "heartbeat" to the server every few seconds or minutes. 要准确计算谁登录并访问该站点,您需要每个客户端每隔几秒或几分钟向服务器发送一次“心跳”。 on each heartbeat trigger you would want to expire any users that have not checked in within the allotted time frame. 在每个心跳触发器上,您希望使所有未在指定时间范围内签入的用户到期。

The heartbeat signal would probably best consist of the username and a timestamp at a minimum, but could include any information you want to track. 心跳信号可能最好由用户名和时间戳组成,但可能包含您要跟踪的任何信息。

When a client sends a single to the server have it check for an existing record for that username and overwrite the timestamp information if a record already exists, otherwise add a new one. 当客户端向服务器发送单个数据库时,它会检查该用户名的现有记录,并在记录已存在时覆盖时间戳信息,否则添加新记录。 Afterwords drop any user entries that have not checked in. Probably best to have the signal happen more often than the expiration. Afterwords删除任何未签入的用户条目。可能最好让信号比到期时更频繁地发生。 like signal every 30 seconds and clean up every minute. 像信号每30秒一样,每分钟清理一次。

(Edited, changed my mind, better to do it all in the same sequence instead of separately) Then return the currently logged in users from your active table which would be as easy as a SELECT * FROM table since the table will always be clean. (编辑,改变了主意,最好以相同的顺序而不是单独执行)然后从活动表返回当前登录的用户,这将像SELECT * FROM table一样简单,因为表将始终是干净的。

Client Side: 客户端:

Here is a light example of a client-side library to handle firing the heartbeat function and catching the results. 下面是一个客户端库的示例,用于处理触发心跳功能和捕获结果。

//Client-side parent variable declaration (simulated namespacing)
var Client = Client || {};
Client.Pulse = null; //Holds a pointer to the heartbeat timer (id)
/* If you needed to cancel the heartbeat processes you could
 * pass this variable to clearTimeout(). Calling Client.Heartbeat()
 * again would start the cycle back up.
 */

//Initial event that will kick off the chain when the DOM is ready
$(document).ready(function(){
  Client.Heartbeat(); //Initial call to the Heartbeat function
});//ready

/// Sends the heartbeat signal and retrieves the currently active user list
Client.Heartbeat = function(){
  var sUsername = 'SomeUser';
  /* Note: If you have an active session running on the server it would not be 
   * necessary to send the username since you could pull it on the backend 
   * script which would be more tamper-proof anyway. I'm just giving an
   * example of sending data to the server using the jQuery.ajax method
   * If you were storing the username to be sent from the client; this wouldn't 
   * be a good place to do it anyway
   * 
   * Remove the "data : {...}" line below to exclude sending information to the server
   * The "type : 'post'" line would not be necessary either 
   */

  $.ajax({ //Send the signal and recieve the information about active users back
    url : '/lib/server/Heartbeat.php',
    type : 'post',
    dataType : 'json',
    data : {Username : sUsername },
    success : function(jActiveUsers,sStatus,jqXHR){ 
      /* This is the callback function of the request, jActiveUsers will be the 
       * json object with the information you choose to send back to it
       */
      Client.RenderActiveUsers(jActiveUsers); //Call the display function
      //Trigger the next delayed call to Client.Heartbeat
      Client.Pulse = setTimeout(function(){
        Client.Heartbeat();
      },30000); //30 second delay before next trigger
    }//success
  });//$.ajax
}//Heartbeat

/// Processes the results sent by the server and draws them to the UI
Client.RenderActiveUsers = function(jActiveUsers){
  /* This is where you would get a handle whatever element(s) on the page
   * will be displaying the information about currently active users
   * and filling it with the list of users how ever you would wish to display it.
   */
}//RenderActiveUsers

Because you will be dealing with asynchronous callbacks setTimeout() calls at the end of a full cycle to start the process over again will be a cleaner way of handling the interval if you were to use setInterval() and the server took longer than expected to return you could see the client start to race on itself. 因为你将处理异步回调setTimeout()调用在一个完整周期结束时重新启动进程将是一个更简洁的处理间隔的方法,如果你使用setInterval()并且服务器花了比预期更长的时间回来你可以看到客户开始竞争自己。 Using a setTimeout() within a successful callback also allows you to fail gracefully in the event the server-side heartbeat processor stops working; 在成功回调中使用setTimeout()还可以在服务器端心跳处理器停止工作时正常失败; so will the client side instead of continuing to make failed attempts (if you want it to keep trying you just need to add a retrigger on a failed response as well). 客户端也是如此,而不是继续尝试失败(如果你希望它继续尝试你只需要在失败的响应上添加重新触发)。

Server Side: 服务器端:

I apologize I am not familiar with Java as a back-end service, I will be making some assumptions based on how PHP works; 我很抱歉我不熟悉Java作为后端服务,我将根据PHP的工作原理做一些假设; so I cannot guarantee it will map directly to your environment. 所以我无法保证它会直接映射到您的环境。 Database examples will assume MySQL. 数据库示例将假设MySQL。 code examples will be pseudo-cody PHP(ish) 代码示例将是伪代码PHP(ish)

On the server end of it you will need a new table for tracking the active users. 在服务器端,您将需要一个新表来跟踪活动用户。 You will possibly already be tracking when they log in within the database but this would be separate from that system (though you could of course link to it to get extra user details for your return structure) 您可能已经在数据库中登录时进行跟踪,但这将与该系统分开(尽管您可以链接到它以获取返回结构的额外用户详细信息)

The table would look at a minimum something like: 该表将至少看起来像:

 ActiveUsers
 -----------------------------------------
 |   Field    |    Type     | NULL | Key |
 -----------------------------------------
 | Id         | int         |      | PRI |
 | Username   | varchar(xx) |      |     |
 | LastPulse  | datetime    |      |     |
 | FirstPulse | datetime    |      |     |
 -----------------------------------------

(speculation) I'm assuming that like PHP there are Sessions in Java which you can use to store information about a particular visitor like their current status. (推测)我假设像PHP一样,Java中有Sessions ,您可以使用它来存储特定访问者的信息,例如他们当前的状态。 In PHP this works by passing an identifier back and forth between the client and server, allowing the server to identify a particular client and for you on the back-end to store variables related to that session (For instance a boolean with the current login state of the user, or a string to hold their username once logged in.) 在PHP中,这通过在客户端和服务器之间来回传递标识符来工作,允许服务器识别特定客户端,并在后端存储与该会话相关的变量(例如,具有当前登录状态的布尔值)用户或登录后用于保存用户名的字符串。)

If this is available to you it would be a much more secure way to handle authentication than to store this information client-side and allow the client to indicate if and as who it is logged in. Herein assuming it is.... 如果您可以使用它,那么处理身份验证的方式要比在客户端存储此信息更安全,并允许客户端指示是否以及登录的人员。这里假设它是....

When the client sends the heartbeat to the server you can access their logged in state and username from the session variables if they are in-fact logged in to begin the process. 当客户端将心跳发送到服务器时,如果它们事实上已登录以开始该过程,则可以从会话变量访问其登录状态和用户名。

if($LoggedIn && ($Username != null)){ //Session information

If they are not logged in you would skip down to the list retrieval part since you won't need to add or modify a record for them 如果他们没有登录,您将跳到列表检索部分,因为您不需要为它们添加或修改记录

Check if they have a record in the active table 检查它们是否在活动表中有记录

SELECT `Id` FROM `ActiveUsers` WHERE `Username` = '{$Username}' LIMIT 1

If a record exists it means they have already checked in before and you want to update the record with a new timestamp using the Id value returned from the first query 如果存在记录,则表示它们之前已经签入,并且您希望使用从第一个查询返回的Id值使用新时间戳更新记录

UPDATE `ActiveUsers` SET `LastPulse` = NOW() WHERE `Id` = {$Id}

If no record exists you will want to make a new one for this user instead 如果不存在记录,则需要为此用户创建一个新记录

INSERT INTO `ActiveUsers` (`Username`,`LastPulse`,`FirstPulse`) VALUES ('{$Username}',NOW(),NOW()) 

Next comes the maintenance phase of the process where you clean up any entries that have not checked in with in the amount of time you want to set as the limit (2 minutes in this example) 接下来是流程的维护阶段,在此过程中,您要清除未设置的任何条目,并将其设置为您要设置为限制的时间(本示例中为2分钟)

DELETE FROM `ActiveUsers` WHERE `LastPulse` < (NOW() - INTERVAL 2 MINUTE)

This will leave your ActiveUsers table so that only records for active users exist which you can now query against to get, along with any other information you want from this and any other table you can link to 这将留下您的ActiveUsers表,以便只存在您可以查询以获取的活动用户的记录,以及您希望从此处以及您可以链接到的任何其他表中获得的任何其他信息

SELECT `Username`, UNIX_TIMESTAMP(`FirstPulse`) AS `FirstPulse` FROM `ActiveUsers` ORDER BY `FirstPulse` ASC

(In PHP) You would then need to loop over the result set and build an array of users which would be converted to JSON with a call to json_encode() and print() ed along with an "application/json" header value so that jQuery can process it properly. (在PHP中)然后,您需要循环结果集并构建一个用户数组,通过调用json_encode()print()以及"application/json"标头值将其转换为JSON,以便jQuery可以正确处理它。 This will of course differ between Java in implementation but the overall process of "create an array, convert it to a JSON string and print it out with a proper header specified" will be the same. 这当然会在实现中的Java之间有所不同,但是“创建一个数组,将其转换为JSON字符串并使用指定的正确标头打印出来”的整个过程将是相同的。

Ideally you want to keep the client as "dumb" as possible to any type of authentication process. 理想情况下,您希望将客户端尽可能“愚蠢”地保留在任何类型的身份验证过程中。 In this example the client is blindly checking in with the server and triggering a cleanup of expired users just by asking for a new list of the active users. 在此示例中,客户端盲目地检入服务器并仅通过询问活动用户的新列表来触发过期用户的清理。

If a 100% accurate list is mission-critical on a highly utilized site it may be necessary to lock the table while performing the maintenance portions. 如果100%准确的列表在高度利用的站点上是关键任务的,则可能需要在执行维护部分时锁定表。 to ensure no queries for the user list occur while another thread is in the check-in phase. 确保在另一个线程处于签入阶段时不会发生对用户列表的查询。

(Wow, this turned into a Wall-O-Text) (哇,这变成了一个Wall-O-Text)

You can periodically make an ajax call to the server and check how many have logged in currently. 您可以定期对服务器进行ajax调用,并检查当前登录的数量。 You could use setInterval for setting up a timer to fire the ajax request. 您可以使用setInterval设置计时器以触发ajax请求。 The response would contain the no. 答复将包含否。 of users active currently. 目前有效的用户

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM